Variabiliteit van steekproef tot steekproef
Om te begrijpen dat een steekproef random is zouden we hetzelfde experiment veel keer moeten kunnen herhalen (repeated sampling).
Dan zouden we inzicht kunnen krijgen hoe de gegevens veranderen van steekproef tot steekproef.
Om dit te illustreren zullen we gebruik maken van een hele grote studie.
Uit die studie zullen we dan herhaaldelijk kleine steekproeven trekken om te begrijpen hoe de gegevens en statistieken veranderen van steekproef tot steekproef. Of om met andere woorden na te gaan wat de variabiliteit is tussen steekproeven.
National Health And Nutrition Examination Study (NHANES)
- Sinds 1960 worden elk jaar mensen van alle leeftijden geïnterviewd bij hen thuis.
- Er maakt ook een gezondheidsonderzoek deel uit van de study die in een mobiel onderzoekscentrum wordt afgenomen.
- We zullen deze grote studie gebruiken om at random personen te selecteren van de Amerikaanse populatie.
- Dat zal inzicht geven in hoe de gegevens en resultaten van een analyse zullen variëren van steekproef tot steekproef.
- De data van deze studie is terug te vinden in het R pakket
NHANES
library(NHANES)
head(NHANES)
# A tibble: 6 x 76
ID SurveyYr Gender Age AgeDecade AgeMonths Race1 Race3 Education
<int> <fct> <fct> <int> <fct> <int> <fct> <fct> <fct>
1 51624 2009_10 male 34 " 30-39" 409 White <NA> High Sch…
2 51624 2009_10 male 34 " 30-39" 409 White <NA> High Sch…
3 51624 2009_10 male 34 " 30-39" 409 White <NA> High Sch…
4 51625 2009_10 male 4 " 0-9" 49 Other <NA> <NA>
5 51630 2009_10 female 49 " 40-49" 596 White <NA> Some Col…
6 51638 2009_10 male 9 " 0-9" 115 White <NA> <NA>
# … with 67 more variables: MaritalStatus <fct>, HHIncome <fct>,
# HHIncomeMid <int>, Poverty <dbl>, HomeRooms <int>, HomeOwn <fct>,
# Work <fct>, Weight <dbl>, Length <dbl>, HeadCirc <dbl>, Height <dbl>,
# BMI <dbl>, BMICatUnder20yrs <fct>, BMI_WHO <fct>, Pulse <int>,
# BPSysAve <int>, BPDiaAve <int>, BPSys1 <int>, BPDia1 <int>,
# BPSys2 <int>, BPDia2 <int>, BPSys3 <int>, BPDia3 <int>,
# Testosterone <dbl>, DirectChol <dbl>, TotChol <dbl>, UrineVol1 <int>,
# UrineFlow1 <dbl>, UrineVol2 <int>, UrineFlow2 <dbl>, Diabetes <fct>,
# DiabetesAge <int>, HealthGen <fct>, DaysPhysHlthBad <int>,
# DaysMentHlthBad <int>, LittleInterest <fct>, Depressed <fct>,
# nPregnancies <int>, nBabies <int>, Age1stBaby <int>,
# SleepHrsNight <int>, SleepTrouble <fct>, PhysActive <fct>,
# PhysActiveDays <int>, TVHrsDay <fct>, CompHrsDay <fct>,
# TVHrsDayChild <int>, CompHrsDayChild <int>, Alcohol12PlusYr <fct>,
# AlcoholDay <int>, AlcoholYear <int>, SmokeNow <fct>, Smoke100 <fct>,
# Smoke100n <fct>, SmokeAge <int>, Marijuana <fct>, AgeFirstMarij <int>,
# RegularMarij <fct>, AgeRegMarij <int>, HardDrugs <fct>, SexEver <fct>,
# SexAge <int>, SexNumPartnLife <int>, SexNumPartYear <int>,
# SameSex <fct>, SexOrientation <fct>, PregnantNow <fct>
Observations: 10,000
Variables: 76
$ ID <int> 51624, 51624, 51624, 51625, 51630, 51638, 51646…
$ SurveyYr <fct> 2009_10, 2009_10, 2009_10, 2009_10, 2009_10, 20…
$ Gender <fct> male, male, male, male, female, male, male, fem…
$ Age <int> 34, 34, 34, 4, 49, 9, 8, 45, 45, 45, 66, 58, 54…
$ AgeDecade <fct> 30-39, 30-39, 30-39, 0-9, 40-49, 0-9, 0-…
$ AgeMonths <int> 409, 409, 409, 49, 596, 115, 101, 541, 541, 541…
$ Race1 <fct> White, White, White, Other, White, White, White…
$ Race3 <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ Education <fct> High School, High School, High School, NA, Some…
$ MaritalStatus <fct> Married, Married, Married, NA, LivePartner, NA,…
$ HHIncome <fct> 25000-34999, 25000-34999, 25000-34999, 20000-24…
$ HHIncomeMid <int> 30000, 30000, 30000, 22500, 40000, 87500, 60000…
$ Poverty <dbl> 1.36, 1.36, 1.36, 1.07, 1.91, 1.84, 2.33, 5.00,…
$ HomeRooms <int> 6, 6, 6, 9, 5, 6, 7, 6, 6, 6, 5, 10, 6, 10, 10,…
$ HomeOwn <fct> Own, Own, Own, Own, Rent, Rent, Own, Own, Own, …
$ Work <fct> NotWorking, NotWorking, NotWorking, NA, NotWork…
$ Weight <dbl> 87.4, 87.4, 87.4, 17.0, 86.7, 29.8, 35.2, 75.7,…
$ Length <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ HeadCirc <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ Height <dbl> 164.7, 164.7, 164.7, 105.4, 168.4, 133.1, 130.6…
$ BMI <dbl> 32.22, 32.22, 32.22, 15.30, 30.57, 16.82, 20.64…
$ BMICatUnder20yrs <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ BMI_WHO <fct> 30.0_plus, 30.0_plus, 30.0_plus, 12.0_18.5, 30.…
$ Pulse <int> 70, 70, 70, NA, 86, 82, 72, 62, 62, 62, 60, 62,…
$ BPSysAve <int> 113, 113, 113, NA, 112, 86, 107, 118, 118, 118,…
$ BPDiaAve <int> 85, 85, 85, NA, 75, 47, 37, 64, 64, 64, 63, 74,…
$ BPSys1 <int> 114, 114, 114, NA, 118, 84, 114, 106, 106, 106,…
$ BPDia1 <int> 88, 88, 88, NA, 82, 50, 46, 62, 62, 62, 64, 76,…
$ BPSys2 <int> 114, 114, 114, NA, 108, 84, 108, 118, 118, 118,…
$ BPDia2 <int> 88, 88, 88, NA, 74, 50, 36, 68, 68, 68, 62, 72,…
$ BPSys3 <int> 112, 112, 112, NA, 116, 88, 106, 118, 118, 118,…
$ BPDia3 <int> 82, 82, 82, NA, 76, 44, 38, 60, 60, 60, 64, 76,…
$ Testosterone <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ DirectChol <dbl> 1.29, 1.29, 1.29, NA, 1.16, 1.34, 1.55, 2.12, 2…
$ TotChol <dbl> 3.49, 3.49, 3.49, NA, 6.70, 4.86, 4.09, 5.82, 5…
$ UrineVol1 <int> 352, 352, 352, NA, 77, 123, 238, 106, 106, 106,…
$ UrineFlow1 <dbl> NA, NA, NA, NA, 0.094, 1.538, 1.322, 1.116, 1.1…
$ UrineVol2 <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ UrineFlow2 <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ Diabetes <fct> No, No, No, No, No, No, No, No, No, No, No, No,…
$ DiabetesAge <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ HealthGen <fct> Good, Good, Good, NA, Good, NA, NA, Vgood, Vgoo…
$ DaysPhysHlthBad <int> 0, 0, 0, NA, 0, NA, NA, 0, 0, 0, 10, 0, 4, NA, …
$ DaysMentHlthBad <int> 15, 15, 15, NA, 10, NA, NA, 3, 3, 3, 0, 0, 0, N…
$ LittleInterest <fct> Most, Most, Most, NA, Several, NA, NA, None, No…
$ Depressed <fct> Several, Several, Several, NA, Several, NA, NA,…
$ nPregnancies <int> NA, NA, NA, NA, 2, NA, NA, 1, 1, 1, NA, NA, NA,…
$ nBabies <int> NA, NA, NA, NA, 2, NA, NA, NA, NA, NA, NA, NA, …
$ Age1stBaby <int> NA, NA, NA, NA, 27, NA, NA, NA, NA, NA, NA, NA,…
$ SleepHrsNight <int> 4, 4, 4, NA, 8, NA, NA, 8, 8, 8, 7, 5, 4, NA, 5…
$ SleepTrouble <fct> Yes, Yes, Yes, NA, Yes, NA, NA, No, No, No, No,…
$ PhysActive <fct> No, No, No, NA, No, NA, NA, Yes, Yes, Yes, Yes,…
$ PhysActiveDays <int> NA, NA, NA, NA, NA, NA, NA, 5, 5, 5, 7, 5, 1, N…
$ TVHrsDay <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ CompHrsDay <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ TVHrsDayChild <int> NA, NA, NA, 4, NA, 5, 1, NA, NA, NA, NA, NA, NA…
$ CompHrsDayChild <int> NA, NA, NA, 1, NA, 0, 6, NA, NA, NA, NA, NA, NA…
$ Alcohol12PlusYr <fct> Yes, Yes, Yes, NA, Yes, NA, NA, Yes, Yes, Yes, …
$ AlcoholDay <int> NA, NA, NA, NA, 2, NA, NA, 3, 3, 3, 1, 2, 6, NA…
$ AlcoholYear <int> 0, 0, 0, NA, 20, NA, NA, 52, 52, 52, 100, 104, …
$ SmokeNow <fct> No, No, No, NA, Yes, NA, NA, NA, NA, NA, No, NA…
$ Smoke100 <fct> Yes, Yes, Yes, NA, Yes, NA, NA, No, No, No, Yes…
$ Smoke100n <fct> Smoker, Smoker, Smoker, NA, Smoker, NA, NA, Non…
$ SmokeAge <int> 18, 18, 18, NA, 38, NA, NA, NA, NA, NA, 13, NA,…
$ Marijuana <fct> Yes, Yes, Yes, NA, Yes, NA, NA, Yes, Yes, Yes, …
$ AgeFirstMarij <int> 17, 17, 17, NA, 18, NA, NA, 13, 13, 13, NA, 19,…
$ RegularMarij <fct> No, No, No, NA, No, NA, NA, No, No, No, NA, Yes…
$ AgeRegMarij <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 20,…
$ HardDrugs <fct> Yes, Yes, Yes, NA, Yes, NA, NA, No, No, No, No,…
$ SexEver <fct> Yes, Yes, Yes, NA, Yes, NA, NA, Yes, Yes, Yes, …
$ SexAge <int> 16, 16, 16, NA, 12, NA, NA, 13, 13, 13, 17, 22,…
$ SexNumPartnLife <int> 8, 8, 8, NA, 10, NA, NA, 20, 20, 20, 15, 7, 100…
$ SexNumPartYear <int> 1, 1, 1, NA, 1, NA, NA, 0, 0, 0, NA, 1, 1, NA, …
$ SameSex <fct> No, No, No, NA, Yes, NA, NA, Yes, Yes, Yes, No,…
$ SexOrientation <fct> Heterosexual, Heterosexual, Heterosexual, NA, H…
$ PregnantNow <fct> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
Data exploratie
Onderzoeksvraag: hoe verschilt de lengte van volwassen mannen en vrouwen.
- We pipen de dataset naar de function
filter om de data te filteren volgens leeftijd.
- We plotten de lengte metingen.
- We selecteren de data data met het commando
ggplot(aes(x=lengte))
- We voegen een histogram toe met het commando
geom_histogram()
- We maken twee vertikale panels met het commando
facet_grid(Gender~.)
- We veranderen het label van de x-as met de
xlab functie.
NHANES%>%
filter(Age > 18 & !is.na(Height)) %>%
ggplot(aes(x = Height))+
geom_histogram() +
facet_grid(Gender ~ .) +
xlab("Lengte (cm)")

We zien dat de data nu min of meer symmetrisch verdeeld zijn en een klokvorm hebben.
Dat zal ons toe laten om de data verder samen te vatten door gebruik te maken van twee statistieken: het gemiddelde en de standaard deviatie wat een maat is voor de spreiding van de gegevens rond het gemiddelde.
We maken nu een subset van de data die we zullen gebruiken om aan te tonen hoe de variabiliteit in kleine steekproeven kan variëren van steekproef tot steekproef.
- We filteren op leeftijd en verwijderen ontbrekenden gegevens (NA, Not Available).
- We selecteren enkel het geslacht en Lengte zodat de dataset geen onnodige variabelen bevat.
nhanesSub <- NHANES %>%
filter(Age > 25 & !is.na(Height)) %>%
select(c("Gender","Height"))
We berekenen het gemiddelde en de standaard deviatie voor de lengte voor mannen en vrouwen in de grote dataset. We groeperen de data hiervoor op basis van het geslacht (variable Gender).
HeightSum <- nhanesSub %>%
group_by(Gender) %>%
summarize_at("Height",
list(mean = mean,
sd = sd)
)
knitr::kable(
HeightSum %>%
mutate_if(is.numeric, round, digits=1)
)
| female |
161.9 |
7.2 |
| male |
175.8 |
7.5 |
Experiment
Stel dat we geen toegang hebben tot de metingen van de NHANES studie.
We zouden dan een experiment op moeten zetten om metingen bij mannen en vrouwen te doen.
Veronderstel dat we budget hebben om metingen bij 5 mannen en 5 vrouwen te doen.
We zouden dan 5 mannen en 5 vrouwen boven de 25 jaar at random selecteren uit de Amerikaanse populatie.
We kunnen dit experiment simuleren door 5 vrouwen en 5 mannen at random te selecteren uit de NHANES studie.
set.seed(1000001)
nSamp <- 5
fem <- nhanesSub %>%
filter(Gender=="female") %>%
sample_n(size=5)
mal <- nhanesSub %>%
filter(Gender=="male") %>%
sample_n(size=5)
samp1 <- rbind(fem,mal)
samp1
# A tibble: 10 x 2
Gender Height
<fct> <dbl>
1 female 159.
2 female 168.
3 female 157.
4 female 155.
5 female 163.
6 male 178.
7 male 173.
8 male 187.
9 male 173.
10 male 185.
Data Exploratie
samp1 %>%
ggplot(aes(x=Height)) +
geom_histogram() +
facet_grid(Gender~.) +
xlab("Lengte (cm)")

HeightSumExp1 <- samp1 %>%
group_by(Gender) %>%
summarize_at("Height",
list(mean = mean,
sd = sd)
)
HeightSumExp1
# A tibble: 2 x 3
Gender mean sd
<fct> <dbl> <dbl>
1 female 161. 5.17
2 male 179. 6.49
Histogram is niet zinvol als we maar zo weinig datapunten hebben.
Boxplot is beter:

We voeren hier ook een t-test uit.
t.test(Height~Gender,data=samp1)
Welch Two Sample t-test
data: Height by Gender
t = -4.9713, df = 7.6177, p-value = 0.001261
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-27.068985 -9.811015
sample estimates:
mean in group female mean in group male
160.62 179.06
In het experiment zijn vrouwen zijn gemiddeld 18.44 cm kleiner dan mannen. En als we een statistische test uitvoeren (zie hoofdstuk 5: Statistische besluitvorming) kunnen we besluiten dat dit verschil statistisch significant is.
Herhaal het experiment
Als we het experiment herhalen selecteren we andere mensen en verkrijgen we andere resultaten.
fem <- nhanesSub %>%
filter(Gender=="female") %>%
sample_n(size=5)
mal <- nhanesSub %>%
filter(Gender=="male") %>%
sample_n(size=5)
samp2 <- rbind(fem,mal)
HeightSumExp2 <- samp2 %>%
group_by(Gender) %>%
summarize_at("Height",
list(mean=mean,
sd=sd)
)
HeightSumExp2
# A tibble: 2 x 3
Gender mean sd
<fct> <dbl> <dbl>
1 female 169. 9.38
2 male 175. 6.12
samp2 %>%
ggplot(aes(x = Gender,y = Height)) +
geom_boxplot(outlier.shape = NA) +
geom_point(position = "jitter") +
geom_point(
aes(x = 1, y = HeightSumExp1$mean[1]),
size = 3,
pch = 17,
color="darkred") +
geom_point(
aes(x = 2, y = HeightSumExp1$mean[1]),
size = 3,
pch = 17,
color = "darkred") +
ylab("Height (cm)")

t.test(Height ~ Gender, data=samp2)
Welch Two Sample t-test
data: Height by Gender
t = -1.1379, df = 6.8813, p-value = 0.2932
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-17.586435 6.186435
sample estimates:
mean in group female mean in group male
169.06 174.76
In de nieuwe steekproef zijn vrouwen zijn gemiddeld 5.7 cm kleiner dan mannen. En dit verschil is statistisch niet significant
Herhaal het experiment opnieuw
seed <- 1336602
fem <- nhanesSub %>%
filter(Gender=="female") %>%
sample_n(size=5)
mal <- nhanesSub %>%
filter(Gender=="male") %>%
sample_n(size=5)
samp3 <- rbind(fem,mal)
HeightSumExp3 <- samp3 %>%
group_by(Gender) %>%
summarize_at("Height",
list(mean=mean,
sd=sd)
)
HeightSumExp3
# A tibble: 2 x 3
Gender mean sd
<fct> <dbl> <dbl>
1 female 162. 12.5
2 male 170. 14.5
samp3 %>%
ggplot(aes(x = Gender,y = Height)) +
geom_boxplot(outlier.shape = NA) +
geom_point(position = "jitter") +
geom_point(
aes(x = 1, y = HeightSumExp1$mean[1]),
size = 3,
pch = 17,
color="darkred") +
geom_point(
aes(x = 2, y = HeightSumExp1$mean[1]),
size = 3,
pch = 17,
color = "darkred") +
ylab("Height (cm)")

t.test(Height ~ Gender, data=samp3)
Welch Two Sample t-test
data: Height by Gender
t = -0.99138, df = 7.8343, p-value = 0.3511
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
-28.34441 11.34441
sample estimates:
mean in group female mean in group male
161.96 170.46
In de nieuwe steekproef zijn vrouwen gemiddeld 8.5 cm kleiner dan mannen. En dit verschil is statistisch niet significant
Samenvatting
We trokken at random andere proefpersonen in elke steekproef
Hierdoor verschillen lengtemetingen van steekproef tot steekproef.
Dus ook de geschatte gemiddeldes en standaard deviaties.
Bijgevolg zijn onze conclusies ook onzeker en kunnen deze wijzigen van steekproef tot steekproef.
Steekproeven waarbij het effect tegengesteld is aan dat in de populatie en waarbij we besluiten dat het verschil significant is, zijn zeldzaam.
\(\rightarrow\) Met statistiek controleren we de kans op het trekken foute conclusies.
- Dit wordt in de onderstaande code geïllustreerd. We trekken 10000 herhaalde steekproeven van 5 vrouwen en 5 mannen uit de NHANES studie.
# Aantal simulaties en steekproefgrootte per groep
nSim <- 10000
nSamp <- 5
# We filteren de data vooraf zodat we dit niet telkens opnieuw hoeven te doen
fem <- nhanesSub %>%
filter(Gender == "female")
mal <- nhanesSub %>%
filter(Gender == "male")
# Simulatie studie
# Om snelle functies te kunnen gebruiken nemen we eerst nSim steekproeven en berekenen we daarna alles.
femSamps <- malSamps <-matrix(NA, nrow=nSamp, ncol=nSim)
for (i in 1:nSim)
{
femSamps[,i] <- sample(fem$Height, nSamp)
malSamps[,i] <- sample(mal$Height, nSamp)
}
res <- data.frame(
verschil=colMeans(femSamps) - colMeans(malSamps),
Rfast::ttests(femSamps, malSamps)
)
sum(res$pvalue < 0.05 & res$verschil < 0)
[1] 7148
[1] 2852
sum(res$pvalue < 0.05 & res$verschil>0)
[1] 0
res %>%
ggplot(aes(x=verschil,y=-log10(pvalue),color=pvalue < 0.05)) +
geom_point() +
xlab("Gemiddeld Verschil (cm)") +
ylab("Statistische Significantie (-log10 p)")

res %>%
ggplot(aes(y = verschil)) +
geom_boxplot() +
ylab("Gemiddeld Verschil (cm)")

$x
[1] ""
attr(,"class")
[1] "labels"
Op basis van 10 000 steekproeven van 5 mannen en 5 vrouwen zagen we dat in 7148 steekproeven vrouwen gemiddeld significant kleiner zijn dan mannen. In 2852 steekproeven besluiten we dat vrouwen en mannen gemiddeld niet significant verschillen in lengte. En in 0 besluiten we dat vrouwen gemiddeld significant groter zijn dan mannen.
- De steekproef die we toonden waaruit we zouden besluiten dat vrouwen significant groter zijn dan mannen is heel onwaarschijnlijk. Er moesten 1336602 steekproeven worden getrokken om deze extreme steekproef te vinden.
Het feit dat we in veel steekproeven resultaten vinden die statistisch niet significant zijn komt omdat de statistische toets een te lage kracht heeft om het verschil te detecteren wanneer er maar 5 observaties zijn per groep.
Grotere steekproef?
Wat gebeurt er als we de steekproef verhogen naar 50 observaties per groep?
# Aantal simulaties en steekproefgrootte per groep
nSim <- 10000
nSamp <- 50
# We filteren de data vooraf zodat we dit niet telkens opnieuw hoeven te doen
fem <- nhanesSub %>%
filter(Gender == "female")
mal <- nhanesSub %>%
filter(Gender == "male")
# Simulatie studie
# Om snelle functies te kunnen gebruiken nemen we eerst nSim steekproeven en berekenen we daarna alles.
femSamps <- malSamps <- matrix(NA, nrow = nSamp, ncol = nSim)
for (i in 1:nSim)
{
femSamps[,i] <- sample(fem$Height, nSamp)
malSamps[,i] <- sample(mal$Height, nSamp)
}
res <- data.frame(
verschil = colMeans(femSamps) - colMeans(malSamps),
Rfast::ttests(femSamps, malSamps)
)
sum(res$pvalue < 0.05 & res$verschil < 0)
[1] 10000
[1] 0
sum(res$pvalue < 0.05 & res$verschil > 0)
[1] 0
res %>%
ggplot(aes(x=verschil,y=-log10(pvalue),color=pvalue<0.05)) +
geom_point() +
xlab("Gemiddeld Verschil (cm)") +
ylab("Statistische Significantie (-log10 p)")

res %>%
ggplot(aes(y=verschil)) +
geom_boxplot() +
ylab("Gemiddeld Verschil (cm)")

$x
[1] ""
attr(,"class")
[1] "labels"
LS0tCnRpdGxlOiAiMS4gSW50cm9kdWN0aWU6IFdhYXJvbSBTdGF0aXN0aWVrPyIKYXV0aG9yOiAiTGlldmVuIENsZW1lbnQiCmRhdGU6ICJzdGF0T21pY3MsIEdoZW50IFVuaXZlcnNpdHkgKGh0dHBzOi8vc3RhdG9taWNzLmdpdGh1Yi5pbykiCm91dHB1dDoKICAgIGh0bWxfZG9jdW1lbnQ6CiAgICAgIGNvZGVfZG93bmxvYWQ6IHRydWUgICAgCiAgICAgIHRoZW1lOiBjb3NtbwogICAgICB0b2M6IHRydWUKICAgICAgdG9jX2Zsb2F0OiB0cnVlCiAgICAgIGhpZ2hsaWdodDogdGFuZ28KICAgICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCi0tLQoKIyBJbnRyb2R1Y3RpZQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChpbmNsdWRlID0gVFJVRSwgY29tbWVudCA9IE5BLCBlY2hvID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKYGBgCgotIFdlIGxldmVuIGluIGhldCBiaWcgZGF0YSBlcmEKLSBHZWdldmVucyBvdmVyIGxvY2F0aWUsIHN1cmZnZWRyYWcsIGFhbmtvb3BnZWRyYWcsIHNvY2lhbGUgbWVkaWEKLSBXZXRlbnNjaGFwOiBleHByZXNzaWUgbWV0ZW4gdmFuIGR1aXplbmRlbiBnZW5lbiwgZWl3aXR0ZW4sLi4uIHZvb3IgZWxrIHN1YmplY3QKLSBDaGVtaXNjaGUgcHJvY2VzIGNvbnRyb2xlOiBncm9vdCBhYW50YWwgc2Vuc29yZW4gZGllIGNvbnRpbnUgZWVuIHByb2NlcyBtZXRlbiB6b2RhdCBoZXQgcHJvY2VzIGthbiB3b3JkZW4gYmlqZ2VzdHV1cmQKLSBEYXRhIGRyaXZlbiBqb3VybmFsaXNtCi0gLi4uCgpTdGF0aXN0aWVrIGlzIGRlIHdldGVuc2NoYXAgb20gdGUgbGVyZW4gdWl0IGVtcGlyaXNjaGUgZ2VnZXZlbnMKClN0YXRpc3Rpc2NoZSBnZWxldHRlcmRoZWlkIGlzIGNydWNpYWFsIG9tIHJlc3VsdGF0ZW4gZW4gcHVibGljYXRpZXMga3JpdGlzY2ggdGUga3VubmVuIGludGVycHJldGVyZW4uCgojIyBCb3V0YWRlOiBNZXQgc3RhdGlzdGllayBrYW4gamUgYWxsZXMgYmV3aWp6ZW4KCi0tLQoKIyMgTWV0IGZvdXRlIHN0YXRpc3RpZWsga2FuIGplIGFsbGVzIGJld2lqemVuCgotLS0KCkdhcmNpYS1CZXJ0aG91ICYgQWxjYXJheiAoTWVkLiBSZXMuIE1ldGguIDIwMDQpOgoKLSBKYWFyZ2FuZyAyMDAxIHZhbiBOYXR1cmUgZW4gQnJpdGlzaCBNZWRpY2FsIEpvdXJuYWwKLSAzOCUgZW4gMjUlIHZhbiBhcnRpa2VsZW4gYmV2YXQgZWVuIHN0YXRpc3Rpc2NoZSBmb3V0Ci0gMTElOiBmb3V0ZW4gdGVnZW4gaW50ZXJwcmV0YXRpZQotIDQlOiBiZXNsdWl0IHNwcmVla3QgZXZpZGVudGllIHRlZ2VuCgotLS0KCgpodHRwczovL3d3dy5tZWRyeGl2Lm9yZy9jb250ZW50LzEwLjExMDEvMjAyMC4wNy4xNy4yMDE1NTg0NnYxCgohW10oaHR0cHM6Ly9naXRodWIuY29tL3N0YXRPbWljcy9zYmMyMC9yYXcvbWFzdGVyL3RoZW9yeS9maWd1cmVzL0ZvbnNlY2EyMDIwQ292aWRWZWdldGFibGVzLnBuZykKCi0tLQoKIVtdKGh0dHBzOi8vZ2l0aHViLmNvbS9zdGF0T21pY3Mvc2JjMjAvcmF3L21hc3Rlci90aGVvcnkvZmlndXJlcy9jb3ZpZFZlZ2V0YWJsZXMucG5nKQoKLS0tCgohW10oaHR0cHM6Ly9naXRodWIuY29tL3N0YXRPbWljcy9zYmMyMC9yYXcvbWFzdGVyL3RoZW9yeS9maWd1cmVzL2NvdmlkVmVnZXRhYmxlczMucG5nKQoKLS0tCgohW10oaHR0cHM6Ly9naXRodWIuY29tL3N0YXRPbWljcy9zYmMyMC9yYXcvbWFzdGVyL3RoZW9yeS9maWd1cmVzL2NvdmlkVmVnZXRhYmxlczIucG5nKQoKLS0tCgohW10oaHR0cHM6Ly9naXRodWIuY29tL3N0YXRPbWljcy9zYmMyMC9yYXcvbWFzdGVyL3RoZW9yeS9maWd1cmVzL3BuYXNIdW1hbk1vdXNlUGFwZXJUaXRsZS5wbmcpe3dpZHRoPTk1JX0KCiJ0aGUgZXhwcmVzc2lvbiBmb3IgbWFueSBzZXRzIG9mIGdlbmVzIHdhcyBmb3VuZCB0byBiZSBtb3JlIHNpbWlsYXIgaW4gZGlmZmVyZW50IHRpc3N1ZXMgd2l0aGluIHRoZSBzYW1lIHNwZWNpZXMgdGhhbiBiZXR3ZWVuIHNwZWNpZXMuIgoKIk92ZXJhbGwsIG91ciByZXN1bHRzIGluZGljYXRlIHRoYXQgdGhlcmUgaXMgY29uc2lkZXJhYmxlIFJOQSBleHByZXNzaW9uIGRpdmVyc2l0eSBiZXR3ZWVuIGh1bWFucyBhbmQgbWljZSwgd2VsbCBiZXlvbmQgd2hhdCB3YXMgZGVzY3JpYmVkIHByZXZpb3VzbHksIGxpa2VseSByZWZsZWN0aW5nIHRoZSBmdW5kYW1lbnRhbCBwaHlzaW9sb2dpY2FsIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlc2UgdHdvIG9yZ2FuaXNtcy4iCgotLS0KCiFbXShodHRwczovL3Bicy50d2ltZy5jb20vbWVkaWEvQ0RzU3pjVVZBQUFWWHNrP2Zvcm1hdD1wbmcmbmFtZT05MDB4OTAwKQpodHRwczovL3R3aXR0ZXIuY29tL1lfR2lsYWQvc3RhdHVzLzU5MzA4ODQ1MTQ2Mjk2MzIwMgoKLS0tCgohW10oaHR0cHM6Ly9wYnMudHdpbWcuY29tL21lZGlhL0NEc1N6Y0ZVTUFBVndHYT9mb3JtYXQ9cG5nJm5hbWU9c21hbGwpCmh0dHBzOi8vdHdpdHRlci5jb20vWV9HaWxhZC9zdGF0dXMvNTkzMDg4NDUxNDYyOTYzMjAyCgotLS0KCgojIE9rc2VsIG1pY3JvYmlvbWUgdm9vcmJlZWxkCgoKIVtdKGh0dHBzOi8vaW1hZ2VzLnZydC5iZS93aWR0aDEyODAvMjAxOC8wNi8yNy80ZTcyMDk4ZC03YTBkLTExZTgtYWJjYy0wMmI3Yjc2YmY0N2YuanBnKXt3aWR0aD03MCV9CgotIGh0dHBzOi8vd3d3LnZydC5iZS92cnRud3MvbmwvMjAxOC8xMC8yMi9nZXpvY2h0LW1lbnNlbi1tZXQtcGVuZXRyYW50ZS1saWpmZ2V1ci1vbS1wcm9iaW90aXNjaGUtZGVvZG9yLwotIGh0dHBzOi8veW91dHUuYmUvOVJJRnlxTFhkVncKCi0tLQoKLSBPa3NlbGdldXIgd29yZHQgbmlldCB2ZXJvb3J6YWFrdCBkb29yIGhldCB6d2VldCB6ZWxmLiBEZSBnZXVyIGlzIGFma29tc3RpZyB2YW4gc3BlY2lmaWNpZWsgbWljcm8tb3JnYW5pc21lbiB2YW4gZGUgZ3JvZXAgKkNvcnluZWJhY3Rlcml1bSBzcHAuKiBkaWUgaGV0IHp3ZWV0IG1ldGFib2xpc2VyZW4uICpTdGFwaHlsb2NvY2N1cyBzcHAuKiB6aWpuIGVlbiBhbmRlcmUgZ3JvZXAgYmFjdGVyacOrbiBkaWUgb29rIGFidW5kYW50IHppam4gaW4gaGV0IG1pY3JvYmlvbWUgdmFuIGRlIG9rc2VsIGRpZSB6d2VldCBtZXRhYm9saXNlcmVuIG5hYXIgbWV0YWJvbGlldGVuIGRpZSBuaWV0IHN0aW5rZW4uCgotIERlIENNRVQtZ3JvZXAgYWFuIFVHRU5UIGRvZXQgb25kZXJ6b2VrIG5hYXIgaGV0IHRyYW5zcGxhbnRlcmVuIHZhbiBkZSBtaWNyb2Jpw6tsZSBnZW1lZW5zY2hhcCwgaGV0IG1pY3JvYmlvbWUsIG9tIG1lbnNlbiB2YW4gZ2V1cmVuZGUgb2tzZWxzIGFmIHRlIGhlbHBlbi4gIAoKLSBWb29yZ2VzdGVsZGUgdGhlcmFwaWUKICAJMS4gVmVyd2lqZGVyIGhldCBva3NlbCBtaWNyb2Jpb21lIG1ldCBhbnRpYmlvdGljYQogICAgMi4gQmXDr252bG9lZCBoZXQgb2tzZWwgbWljcm9iaW9tZSBkb29yIG1pY3JvYmlvbWUgdGUgdHJhbnNwbGFudGVyZW4gdmFuIGVlbiBpbmRpdmlkdWUgZGllIGdlZW4gZ2V1cmVuZGUgb2tzZWxzIGhlZWZ0IChodHRwczovL3lvdXR1LmJlLzlSSUZ5cUxYZFZ3KQoKCi0tLQoKIyMgUHJvZWZvcHpldCAoZXhwZXJpbWVudGFsIGRlc2lnbikKCmBgYHtyIG91dC53aWR0aD0nODAlJyxmaWcuYXNwPS44LCBmaWcuYWxpZ249J2NlbnRlcicsZWNobz1GQUxTRX0KaWYgKCJwaSIlaW4lbHMoKSkgcm0oInBpIikKa29wdm9ldGVyPC1mdW5jdGlvbih4LHksYW5nbGU9MCxsPS4yLGNleC5kb3Q9LjUscGNoPTE5LGNvbD0iYmxhY2siKQp7CmFuZ2xlPWFuZ2xlLzE4MCpwaQpwb2ludHMoeCx5LGNleD1jZXguZG90LHBjaD1wY2gsY29sPWNvbCkKbGluZXMoYyh4LHgrbCpjb3MoLXBpLzIrYW5nbGUpKSxjKHkseStsKnNpbigtcGkvMithbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsLzIqY29zKC1waS8yK2FuZ2xlKSx4K2wvMipjb3MoLXBpLzIrYW5nbGUpK2wvNCpjb3MoYW5nbGUpKSxjKHkrbC8yKnNpbigtcGkvMithbmdsZSkseStsLzIqc2luKC1waS8yK2FuZ2xlKStsLzQqc2luKGFuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wvMipjb3MoLXBpLzIrYW5nbGUpLHgrbC8yKmNvcygtcGkvMithbmdsZSkrbC80KmNvcyhwaSthbmdsZSkpLGMoeStsLzIqc2luKC1waS8yK2FuZ2xlKSx5K2wvMipzaW4oLXBpLzIrYW5nbGUpK2wvNCpzaW4ocGkrYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbCpjb3MoLXBpLzIrYW5nbGUpLHgrbCpjb3MoLXBpLzIrYW5nbGUpK2wvMipjb3MoLXBpLzIrcGkvNCthbmdsZSkpLGMoeStsKnNpbigtcGkvMithbmdsZSkseStsKnNpbigtcGkvMithbmdsZSkrbC8yKnNpbigtcGkvMitwaS80K2FuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wqY29zKC1waS8yK2FuZ2xlKSx4K2wqY29zKC1waS8yK2FuZ2xlKStsLzIqY29zKC1waS8yLXBpLzQrYW5nbGUpKSxjKHkrbCpzaW4oLXBpLzIrYW5nbGUpLHkrbCpzaW4oLXBpLzIrYW5nbGUpK2wvMipzaW4oLXBpLzItcGkvNCthbmdsZSkpLGNvbD1jb2wpCn0KCnBhcihtYXI9YygwLDAsMCwwKSxtYWk9YygwLDAsMCwwKSkKcGxvdCgwLDAseGxhYj0iIix5bGFiPSIiLHhsaW09YygwLDEwKSx5bGltPWMoMCwxMCksY29sPTAseGF4dD0ibm9uZSIseWF4dD0ibm9uZSIsYXhlcz1GQUxTRSkKcmVjdCgwLDYsMTAsMTAsYm9yZGVyPSJyZWQiLGx3ZD0yKQp0ZXh0KC41LDgsInBvcHVsYXRpb24iLHNydD05MCxjb2w9InJlZCIsY2V4PTIpCnN5bWJvbHMgKDMsIDgsIGNpcmNsZXM9MS41LCBjb2w9InJlZCIsYWRkPVRSVUUsZmc9InJlZCIsaW5jaGVzPUZBTFNFLGx3ZD0yKQpzZXQuc2VlZCgzMzApCmdyaWQ9c2VxKDAsMS4zLC4wMSkKCmZvciAoaSBpbiAxOjUwKQp7CglhbmdsZTE9cnVuaWYobj0xLG1pbj0wLG1heD0zNjApCglhbmdsZTI9cnVuaWYobj0xLG1pbj0wLG1heD0zNjApCglyYWRpdXM9c2FtcGxlKGdyaWQscHJvYj1ncmlkXjIqcGkvc3VtKGdyaWReMipwaSksc2l6ZT0xKQoJa29wdm9ldGVyKDMrcmFkaXVzKmNvcyhhbmdsZTEvMTgwKnBpKSw4K3JhZGl1cypzaW4oYW5nbGUxLzE4MCpwaSksYW5nbGU9YW5nbGUyKQp9CnRleHQoNy41LDgsIk1pY3JvYmlvbWUgaW4gcG9wdWxhdGlvbiIsY29sPSJyZWQiLGNleD0xLjIpCmBgYAoKLS0tCgoKYGBge3Igb3V0LndpZHRoPSc4MCUnLGZpZy5hc3A9LjgsIGZpZy5hbGlnbj0nY2VudGVyJyxlY2hvPUZBTFNFfQppZiAoInBpIiVpbiVscygpKSBybSgicGkiKQprb3B2b2V0ZXI8LWZ1bmN0aW9uKHgseSxhbmdsZT0wLGw9LjIsY2V4LmRvdD0uNSxwY2g9MTksY29sPSJibGFjayIpCnsKYW5nbGU9YW5nbGUvMTgwKnBpCnBvaW50cyh4LHksY2V4PWNleC5kb3QscGNoPXBjaCxjb2w9Y29sKQpsaW5lcyhjKHgseCtsKmNvcygtcGkvMithbmdsZSkpLGMoeSx5K2wqc2luKC1waS8yK2FuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wvMipjb3MoLXBpLzIrYW5nbGUpLHgrbC8yKmNvcygtcGkvMithbmdsZSkrbC80KmNvcyhhbmdsZSkpLGMoeStsLzIqc2luKC1waS8yK2FuZ2xlKSx5K2wvMipzaW4oLXBpLzIrYW5nbGUpK2wvNCpzaW4oYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbC8yKmNvcygtcGkvMithbmdsZSkseCtsLzIqY29zKC1waS8yK2FuZ2xlKStsLzQqY29zKHBpK2FuZ2xlKSksYyh5K2wvMipzaW4oLXBpLzIrYW5nbGUpLHkrbC8yKnNpbigtcGkvMithbmdsZSkrbC80KnNpbihwaSthbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsKmNvcygtcGkvMithbmdsZSkseCtsKmNvcygtcGkvMithbmdsZSkrbC8yKmNvcygtcGkvMitwaS80K2FuZ2xlKSksYyh5K2wqc2luKC1waS8yK2FuZ2xlKSx5K2wqc2luKC1waS8yK2FuZ2xlKStsLzIqc2luKC1waS8yK3BpLzQrYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbCpjb3MoLXBpLzIrYW5nbGUpLHgrbCpjb3MoLXBpLzIrYW5nbGUpK2wvMipjb3MoLXBpLzItcGkvNCthbmdsZSkpLGMoeStsKnNpbigtcGkvMithbmdsZSkseStsKnNpbigtcGkvMithbmdsZSkrbC8yKnNpbigtcGkvMi1waS80K2FuZ2xlKSksY29sPWNvbCkKfQoKcGFyKG1hcj1jKDAsMCwwLDApLG1haT1jKDAsMCwwLDApKQpwbG90KDAsMCx4bGFiPSIiLHlsYWI9IiIseGxpbT1jKDAsMTApLHlsaW09YygwLDEwKSxjb2w9MCx4YXh0PSJub25lIix5YXh0PSJub25lIixheGVzPUZBTFNFKQpyZWN0KDAsNiwxMCwxMCxib3JkZXI9InJlZCIsbHdkPTIpCnRleHQoLjUsOCwicG9wdWxhdGlvbiIsc3J0PTkwLGNvbD0icmVkIixjZXg9MikKc3ltYm9scyAoMywgOCwgY2lyY2xlcz0xLjUsIGNvbD0icmVkIixhZGQ9VFJVRSxmZz0icmVkIixpbmNoZXM9RkFMU0UsbHdkPTIpCnNldC5zZWVkKDMzMCkKZ3JpZD1zZXEoMCwxLjMsLjAxKQoKZm9yIChpIGluIDE6NTApCnsKCWFuZ2xlMT1ydW5pZihuPTEsbWluPTAsbWF4PTM2MCkKCWFuZ2xlMj1ydW5pZihuPTEsbWluPTAsbWF4PTM2MCkKCXJhZGl1cz1zYW1wbGUoZ3JpZCxwcm9iPWdyaWReMipwaS9zdW0oZ3JpZF4yKnBpKSxzaXplPTEpCglrb3B2b2V0ZXIoMytyYWRpdXMqY29zKGFuZ2xlMS8xODAqcGkpLDgrcmFkaXVzKnNpbihhbmdsZTEvMTgwKnBpKSxhbmdsZT1hbmdsZTIpCn0KdGV4dCg3LjUsOCwiTWljcm9iaW9tZSBpbiBwb3B1bGF0aW9uIixjb2w9InJlZCIsY2V4PTEuMikKCnJlY3QoMCwwLDEwLDQsYm9yZGVyPSJibHVlIixsd2Q9MikKdGV4dCguNSwyLCJzYW1wbGUiLHNydD05MCxjb2w9ImJsdWUiLGNleD0yKQpzeW1ib2xzICgzLCAyLCBjaXJjbGVzPTEuNSwgY29sPSJyZWQiLGFkZD1UUlVFLGZnPSJibHVlIixpbmNoZXM9RkFMU0UsbHdkPTIpCmZvciAoaSBpbiAwOjEpCglmb3IgKGogaW4gMDo0KQp7CgoJa29wdm9ldGVyKDIuMStqKigzLjktMi4xKS80LDEuMStpLzIsY29sPSJibGFjayIpCn0KZm9yIChpIGluIDI6MykKCWZvciAoaiBpbiAwOjQpCnsKCglrb3B2b2V0ZXIoMi4xK2oqKDMuOS0yLjEpLzQsMS42K2kvMixjb2w9ImJsYWNrIikKfQp0ZXh0KDcuNSwyLCJNaWNyb2Jpb21lIGluIHNhbXBsZSIsY29sPSJibHVlIixjZXg9MS4yKQoKYXJyb3dzKDMsNS45LDMsNC4xLGNvbD0iYmxhY2siLGx3ZD0zKQp0ZXh0KDEuNSw1LCJFWFAuIERFU0lHTiAoMSkiLGNvbD0iYmxhY2siLGNleD0xLjIpCmBgYAoKLS0tCgotIEV4cGVyaW1lbnQ6CgogICAgLSAyMCBwZXJzb25lbiB3b3JkZW4gYXQgcmFuZG9tIHVpdCBkZSBwb3B1bGF0aWUgZ2V0cm9ra2VuIHZhbiBwZXJzb25lbiBtZXQgZWVuIG9rc2VsZ2V1cjogc3RlZWtwcm9lZiByZXByZXNlbnRhdGllZiB2b29yIHBvcHVsYXRpZSEKCiAgICAtIGRlIHBlcnNvbmVuIHdvcmRlbiBhdCByYW5kb20gdmVyZGVlbGQgb3ZlciB0d2VlIGJlaGFuZGVsaW5nc2dyb2VwZW46CgogICAgICAgIC0gcGxhY2VibyAoZW5rZWwgYW50aWJpb3RpY2EpCiAgICAgICAgLSB0cmFuc3BsYW50aWUgKGFudGliaW90aWNhIGVuIG1pY3JvYmnDq2xlIHRyYW5zcGxhbnRhdGllKS4KICAgICAgICAtIFJhbmRvbWlzYXRpZSBpcyBiZWxhbmdyaWprIG9tIGVydm9vciB0ZSB6b3JnZW4gZGF0IGRlIGdyb2VwZW4gdmVyZ2VsaWprYmFhciB6aWpuLgoKICAgIC0gSGV0IG1pY3JvYmlvbWUgd29yZHQgYmVtb25zdGVyZCA2IHdla2VuIG5hIGRlIGJlaGFuZGVsaW5nLgogICAgLSBUaGUgcmVsYXRpdmUgYWJ1bmRhbnRpZSB2YW4gKlN0YXBoeWxvY29jY3VzIHNwcC4qIG9wICpDb3J5bmViYWN0ZXJpdW0gc3BwLiogKyAqU3RhcGh5bG9jb2NjdXMgc3BwLiogaW4gaGV0IG1pY3JvYmlvbWUgd29yZHQgZ2VtZXRlbiB2aWEgREdHRSAoKkRlbmF0dXJpbmcgR3JhZGllbnQgR2VsIEVsZWN0cm9waG9yZXNpcyopLgoKLS0tCgpER0dFCgohW10oaHR0cHM6Ly9qb3VybmFscy5wbG9zLm9yZy9wbG9zb25lL2FydGljbGUvZmlndXJlL2ltYWdlP3NpemU9bGFyZ2UmZG93bmxvYWQ9JmlkPTEwLjEzNzEvam91cm5hbC5wb25lLjAwNzA1MzguZzAwMSl7d2lkdGg9NzAlfQoKaHR0cHM6Ly9kb2kub3JnLzEwLjEzNzEvam91cm5hbC5wb25lLjAwNzA1MzgKCi0tLQoKVmVydGFhbCBvbmRlcnpvZWtzdnJhYWcgbmFhciBpZXRzIHdhdCB3ZSBrdW5uZW4gcXVhbnRpZmljZXJlbjogSXMgZXIgZWVuIHZlcnNjaGlsIGluIHJlbGF0aWV2ZSBhYnVuZGFudGllIHZhbiAqU3RhcGh5bG9jb2NjdXMgc3BwLiogaW4gaGV0IG1pY3JvYmlvbWUgdmFuIGRlIHBsYWNlYm8gZ3JvZXAgZW4gZGUgdHJhbnNwbGFudGF0aWUKCi0tLQoKYGBge3Igb3V0LndpZHRoPSc4MCUnLGZpZy5hc3A9LjgsIGZpZy5hbGlnbj0nY2VudGVyJyxlY2hvPUZBTFNFfQppZiAoInBpIiVpbiVscygpKSBybSgicGkiKQprb3B2b2V0ZXI8LWZ1bmN0aW9uKHgseSxhbmdsZT0wLGw9LjIsY2V4LmRvdD0uNSxwY2g9MTksY29sPSJibGFjayIpCnsKYW5nbGU9YW5nbGUvMTgwKnBpCnBvaW50cyh4LHksY2V4PWNleC5kb3QscGNoPXBjaCxjb2w9Y29sKQpsaW5lcyhjKHgseCtsKmNvcygtcGkvMithbmdsZSkpLGMoeSx5K2wqc2luKC1waS8yK2FuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wvMipjb3MoLXBpLzIrYW5nbGUpLHgrbC8yKmNvcygtcGkvMithbmdsZSkrbC80KmNvcyhhbmdsZSkpLGMoeStsLzIqc2luKC1waS8yK2FuZ2xlKSx5K2wvMipzaW4oLXBpLzIrYW5nbGUpK2wvNCpzaW4oYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbC8yKmNvcygtcGkvMithbmdsZSkseCtsLzIqY29zKC1waS8yK2FuZ2xlKStsLzQqY29zKHBpK2FuZ2xlKSksYyh5K2wvMipzaW4oLXBpLzIrYW5nbGUpLHkrbC8yKnNpbigtcGkvMithbmdsZSkrbC80KnNpbihwaSthbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsKmNvcygtcGkvMithbmdsZSkseCtsKmNvcygtcGkvMithbmdsZSkrbC8yKmNvcygtcGkvMitwaS80K2FuZ2xlKSksYyh5K2wqc2luKC1waS8yK2FuZ2xlKSx5K2wqc2luKC1waS8yK2FuZ2xlKStsLzIqc2luKC1waS8yK3BpLzQrYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbCpjb3MoLXBpLzIrYW5nbGUpLHgrbCpjb3MoLXBpLzIrYW5nbGUpK2wvMipjb3MoLXBpLzItcGkvNCthbmdsZSkpLGMoeStsKnNpbigtcGkvMithbmdsZSkseStsKnNpbigtcGkvMithbmdsZSkrbC8yKnNpbigtcGkvMi1waS80K2FuZ2xlKSksY29sPWNvbCkKfQoKcGFyKG1hcj1jKDAsMCwwLDApLG1haT1jKDAsMCwwLDApKQpwbG90KDAsMCx4bGFiPSIiLHlsYWI9IiIseGxpbT1jKDAsMTApLHlsaW09YygwLDEwKSxjb2w9MCx4YXh0PSJub25lIix5YXh0PSJub25lIixheGVzPUZBTFNFKQpyZWN0KDAsNiwxMCwxMCxib3JkZXI9InJlZCIsbHdkPTIpCnRleHQoLjUsOCwicG9wdWxhdGlvbiIsc3J0PTkwLGNvbD0icmVkIixjZXg9MikKc3ltYm9scyAoMywgOCwgY2lyY2xlcz0xLjUsIGNvbD0icmVkIixhZGQ9VFJVRSxmZz0icmVkIixpbmNoZXM9RkFMU0UsbHdkPTIpCnNldC5zZWVkKDMzMCkKZ3JpZD1zZXEoMCwxLjMsLjAxKQoKZm9yIChpIGluIDE6NTApCnsKCWFuZ2xlMT1ydW5pZihuPTEsbWluPTAsbWF4PTM2MCkKCWFuZ2xlMj1ydW5pZihuPTEsbWluPTAsbWF4PTM2MCkKCXJhZGl1cz1zYW1wbGUoZ3JpZCxwcm9iPWdyaWReMipwaS9zdW0oZ3JpZF4yKnBpKSxzaXplPTEpCglrb3B2b2V0ZXIoMytyYWRpdXMqY29zKGFuZ2xlMS8xODAqcGkpLDgrcmFkaXVzKnNpbihhbmdsZTEvMTgwKnBpKSxhbmdsZT1hbmdsZTIpCn0KdGV4dCg3LjUsOCwiTWljcm9iaW9tZSBpbiBwb3B1bGF0aW9uIixjb2w9InJlZCIsY2V4PTEuMikKCnJlY3QoMCwwLDEwLDQsYm9yZGVyPSJibHVlIixsd2Q9MikKdGV4dCguNSwyLCJzYW1wbGUiLHNydD05MCxjb2w9ImJsdWUiLGNleD0yKQpzeW1ib2xzICgzLCAyLCBjaXJjbGVzPTEuNSwgY29sPSJyZWQiLGFkZD1UUlVFLGZnPSJibHVlIixpbmNoZXM9RkFMU0UsbHdkPTIpCmZvciAoaSBpbiAwOjEpCglmb3IgKGogaW4gMDo0KQp7CgoJa29wdm9ldGVyKDIuMStqKigzLjktMi4xKS80LDEuMStpLzIsY29sPSJwdXJwbGUiKQp9CmZvciAoaSBpbiAyOjMpCglmb3IgKGogaW4gMDo0KQp7CgoJa29wdm9ldGVyKDIuMStqKigzLjktMi4xKS80LDEuNitpLzIsY29sPSJvcmFuZ2UiKQp9CnRleHQoNy41LDIsIk1pY3JvYmlvbWUgaW4gc2FtcGxlIixjb2w9ImJsdWUiLGNleD0xLjIpCgphcnJvd3MoMyw1LjksMyw0LjEsY29sPSJibGFjayIsbHdkPTMpCnRleHQoMS41LDUsIkVYUC4gREVTSUdOICgxKSIsY29sPSJibGFjayIsY2V4PTEuMikKdGV4dCg3LjUsLjUsIkRBVEEgRVhQTE9SQVRJT04gJlxuREVTQ1JJUFRJVkUgU1RBVElTVElDUyAoMikiLGNvbD0iYmxhY2siLGNleD0xLjIpCmBgYAoKLS0tCgojIyBEYXRhIEV4cGxvcmF0aWUgZW4gYmVzY2hyaWp2ZW5kZSBzdGF0aXN0aWVrCgoKLSBEYXRhIGV4cGxvcmF0aWUgaXMgaGVlbCBiZWxhbmdyaWprIG9tIGluemljaHQgdGUga3JpamdlbiBpbiBkZSBkYXRhIGVuIGlzIGVlbiBlc3NlbnRpw6tsZSBlZXJzdGUgc3RhcCBvbSB0ZSBsZXJlbiB1aXQgZGF0YS4KLSBIZXQgd29yZHQgdmFhayBvbmRlcmdld2FhcmRlZXJkIG9mIG92ZXIgaGV0IGhvb2ZkIGdlemllbi4KCi0tLQoKIyMjIEltcG9ydGVlciBkZSBkYXRhCgotIERhdGEgaW4gZGV6ZSBjdXJzdXMgd29yZHQgdmVyd2Vya3QgdmlhIGhldCBzdGF0aXN0aXNjaCBzb2Z0d2FyZSBwYWtrZXQgUi4KLSBEaXQgcGFra2V0IGxhYXQgdG9lIG9tIHRlIGxlcmVuIHVpdCBkYXRhLgotIEluIGRlemUgY3Vyc3VzIGdhYW4gd2UgZGF0YSBlZXJzdCBleHBsb3JlcmVuIG9tIGluemljaHQgdGUgdmVyd2VydmVuIGluIGRlIGdlZ2V2ZW5zIG9tIGRpZSB2ZXJ2b2xnZW5zIHN0YXRpc3Rpc2NoIHRlIHZlcndlcmtlbi4KLSBWb29yYWxlZXIgd2UgaGllcm1lZSB2YW4gc3RhcnQga3VubmVuIGdhYW4gbW9ldGVuIHdlIGRlIGRhdGEgZWVyc3QgaW1wb3J0ZXJlbiBpbiBSLgoKLSBWaWEgaGV0IHZvbGdlbmRlIGNvbW1hbmRvIGt1bm5lbiB3ZSBlbmtlbGUgcmVnZWxzIHZhbiBlZW4gZGF0YSBiZXN0YW5kIGlubGV6ZW4gb20gZGUgc3RydWN0dXVyIHZhbiBoZXQgZGF0YSBiZXN0YW5kIHRlIHdldGVuIHRlIGtvbWVuLgoKYGBge3J9CnJlYWRfbGluZXMoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9zdGF0T21pY3Mvc2JjMjAvbWFzdGVyL2RhdGEvYXJtcGl0LmNzdiIpCmBgYAoKLSBHZWdldmVucyBpbiBoZXQgYmVzdGFuZCB6aWpuIGRvb3IgY29tbWEncyBnZXNjaGVpZGVuLgotIEVsa2UgcmlqIGJldmF0IGRlIGdlZ2V2ZW5zIHZvb3IgMSBwcm9lZnBlcnNvb24KLSBWZXJzY2hpbGxlbmRlIHZhcmlhYmVsZW4gd29yZGVuIGdlbWV0ZW4gcGVyIHBlcnNvb24gZW4gemlqbiB2YW4gZWxrYWFyIGdlc2NoZWlkZW4gZG9vciBlZW4gY29tbWEuIEhldCBiZXN0YW5kIGlzIGNzdiBmb3JtYWF0OiAiY29tbWEgc2VwYXJhdGVkIHZhbHVlcyIuCi0gV2Uga3VubmVuIGJlc3RhbmRlbiBtZXQgZGl0IGZvcm1hYXQgaW5sZXplbiBSIHZpYSBoZXQgY29tbWFuZG8gcmVhZF9jc3YuCi0gV2Ugc2xhYW4gZGUgZGF0YSBvcCBpbiBSIGluIGhldCBvYmplY3QgbWV0IG5hYW0gYXAuIEhpZXJ2b29yIGdlYnJ1aWtlbiB3ZSBkZSBgPC1gIG9wZXJhdG9yLgotIFdlIGdldmVuIGRlIGRhdGEgdGFiZWwgdGVydWcgZG9vciBoZXQgb2JqZWN0IGFhbiB0ZSByb2VwZW4gZG9vciB6aWpuIG5hYW0gdGUgdHlwZW4uCgpgYGB7cn0KYXAgPC0gcmVhZF9jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9zdGF0T21pY3Mvc2JjMjAvbWFzdGVyL2RhdGEvYXJtcGl0LmNzdiIpCmFwCmBgYAoKLS0tCgojIyMgQmVzY2hyaWp2ZW5kZSBzdGF0aXN0aWVrCgotIEluIGFydGlrZWxzIGVuIGRlIG1lZGlhIHdvcmRlbiByZXN1bHRhdGVuIHVpdCBlZW4gc3RlZWtwcm9lZiB2YWFrIGdlcmFwcG9ydGVlcmQgYS5kLmgudi4gZ2VtaWRkZWxkZSBlbiBkZSBzdGFuZGFhcmRhZndpamtpbmcKCi0gV2UgdmF0dGVuIGRlIGRhdGEgZWVyc3Qgc2FtZW4uIFdlIGJlcmVrZW5lbiBoZXQgZ2VtaWRkZWxkZSBlbiBkZSBzdGFuZGFhcmQgZGV2aWF0aWUgKGVlbiBtYWF0IHZvb3IgZGUgc3ByZWlkaW5nLCB6aWUgdm9sZ2VuZGUgaG9vZmRzdHVra2VuKS4KV2Ugc2xhYW4gaGV0IHJlc3VsdGFhdCBoaWVydmFuIG9wIGluIGhldCBvYmplY3QgYXBSZWxTdW0gdmlhIGBhcFJlbFN1bSA8LWAuCgoxLiBXZSBwaXBlbiAodmlhIGAlPiVgKSBoZXQgYGFwYCBkYXRhZnJhbWUgbmFhciBkZSBgZ3JvdXBfYnlgIGZ1bmN0aWUgb20gZGUgZGF0YSB0ZSBncm9lcGVyZW4gcGVyIHRyZWF0bWVudCB0cnQ6IGBncm91cF9ieSh0cnQpYC4KCjIuIFdlIHBpcGVuIGhldCByZXN1bHRhYXQgbmFhciBkZSBgc3VtbWFyaXplX2F0YCBmdW5jdGlvbiBvbSBkZSAicmVsIiB2YXJpYWJsZSBzYW1lbiB0ZSB2YXR0ZW4gZW4gYmVyZWtlbmVuIGhpZXJiaWogaGV0IGdlbWlkZGVsZGUgZW4gc3RhbmRhYXJkYWZ3aWpraW5nLiBPbWRhdCB3ZSBkZSBkYXRhIGVlcnN0IGhlYmJlbiBnZWdyb2VwZWVyZCB6dWxsZW4gd2UgaGV0IGdlbWlkZGVsZGUgZW4gZGUgc3RhbmRhYXJkIGRldmlhdGllIGJlcmVrZW5lbiBwZXIgZ3JvZXAuCgoKCmBgYHtyfQphcFJlbFN1bSA8LSBhcCAlPiUKICBncm91cF9ieSh0cnQpICU+JQogIHN1bW1hcml6ZV9hdCgicmVsIiwKICAgICAgICAgICAgICAgbGlzdChtZWFuPW1lYW4sCiAgICAgICAgICAgICAgICAgICAgc2Q9c2QKICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICApCmBgYAoKV2UgdG9uZW4gdmVydm9sZ2VucyBoZXQgcmVzdWx0YWF0IGRvb3IgaGV0IG9iamVjdCBhcFJlbFN1bSBhYW4gdGUgcm9lcGVuCgpgYGB7cn0KYXBSZWxTdW0KYGBgCgpXZSBrdW5uZW4gb29rIGVlbiB0YWJlbCBpbiBkZSB3ZWJwYWdpbmEgb2YgaGV0IHBkZiBiZXN0YW5kIGludGVncmVyZW4gdmlhIGhldCBjb21tYW5kbyBrYWJsZSB2YW4gaGV0IGtuaXRyIHBha2tldDoKCmBgYHtyfQprbml0cjo6a2FibGUoYXBSZWxTdW0pCmBgYAoKLS0tCgojIyMgR3JhZmlla2VuCgpXZSBtYWtlbiBpbiBkZXplIGN1cnN1cyBnZWJydWlrIHZhbiBoZXQgcGFra2V0IGBnZ3Bsb3QyYCBvbSBncmFmaWVrZW4gdGUgbWFrZW4uICAKTWV0IGRlIGdncGxvdDIgYmlibGlvdGhlZWsga3VubmVuIHdlIGdlbWFra2VsaWprIGdyYWZpZWtlbiBvcGJvdXdlbiBpbiBsYWdlbiAobGF5ZXJzKS4KSGllcmRvb3IgbGVlc3QgZGUgY29kZSB2ZWVsIG1ha2tlbGlqa2VyLgoKIyMjIyBiYXJwbG90CgpCYXIgcGxvdHMgd29yZGVuIGhlZWwgdmVlbCBnZWJydWlrdCBpbiBhcnRpa2VscyBvbSByZXN1bHRhdGVuIHdlZXIgdGUgZ2V2ZW4uCgoxLiBXZSBwaXBlbiBkZSBzYW1lbmdldmF0dGUgZGF0YSBuYWFyIGRlIGZ1bmN0aWUgYGdncGxvdGAuIERhdCBpcyBkZSBiYXNpcyB2YW4gZWxrZSBnZ3Bsb3QuICBXZSBzZWxlY3RlcmVuIGRlIHZhcmlhYmVsZSBtZXQgZGUgYmVoYW5kZWxpbmcgdHJ0IGFscyB4IHZhcmlhYmVsZSBlbiBkZSB2YXJpYWJlbGUgbWV0IG5hYW0gbWVhbiBhbHMgeS12YXJpYWJlbGUgdm9vciBkZSBwbG90LgpXZSBkb2VuIGRpdCBzdGVlZHMgdmlhIGRlIGFlc3RldGljcyBgYWVzYCBmdW5jdGllLiAgIGBhZXMoeD10cnQseT1tZWFuKWAKCjIuIFdlIG1ha2VuIGVlbiBiYXJwbG90IGRvb3IgZWVuIGxhYWcgdG9lIHRlIHZvZWdlbiB2aWEgZGUgIGBnZW9tX2JhcmAgZnVuY3Rpb24uIERlIHN0YXRpc3RpZWsgaXMgYHN0YXQ9ImlkZW50aXR5ImAgb21kYXQgZGUgaG9vZ3RlIHZhbiBkZSBiYXIgZ2VsaWprIGlzIGFhbiBkZSB3YWFyZGUgdm9vciB5IChoaWVyIGhldCBnZW1pZGRlbGRlIHZvb3IgZGUgcmVsYXRpZXZlIGFidW5kYW50aWUpLgoKMy4gV2Ugdm9lZ2VuIGZvdXRlbnZsYWdnZW4gdG9lIG9tIGRlIG9uemVrZXJoZWlkIG9wIGhldCBnZW1pZGRlbGRlIHdlZXIgdGUgZ2V2ZW4uICBXZSBkb2VuIGRpdCB2aWEgZGUgYGdlb21fZXJyb3JiYXJgIGZ1bmN0aWUgZW4gc3BlY2lmacOrcmVuIGhldCBtaW5pbXVtIGVuIG1heGltdW0gdmFuIGRlIGVycm9yIGJhci4gSGV0IGB3aWR0aGAgYXJndW1lbnQgd29yZHQgZ2VicnVpa3Qgb20gZGUgYnJlZWR0ZSB2YW4gZGUgZXJyb3IgYmFyIHNtYWxsZXIgdGUgbWFrZW4gZGF0IGRlemUgdmFuIGRlIGJhci4KCmBgYHtyfQphcFJlbFN1bSAlPiUKICBnZ3Bsb3QoYWVzKHg9dHJ0LHk9bWVhbikpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsKICBnZW9tX2Vycm9yYmFyKGFlcyh5bWluPW1lYW4tc2QseW1heD1tZWFuK3NkKSx3aWR0aD0uMikKYGBgCgotIElzIGRlemUgcGxvdCBpbmZvcm1hdGllZj8/CgotLS0KCiMjIyMgYm94cGxvdHMKCkJhcnBsb3RzIHppam4gZ2VlbiBnb2VkZSBncmFmaWVrZW46CgotIFplIHppam4gbmlldCBpbmZvcm1hdGllZgoKLSBaZSB2aXN1bGFyaXNlcmVuIGVlbiBzYW1lbnZhdHRpbmcgdmFuIGRlIGRhdGEgZG9vciB0d2VlIHB1bnRlbjogYHR3byBwb2ludCBzdW1tYXJ5YDogZ2VtaWRkZWxkZSBlbiBkZSBzdGFuZGFhcmQgZGV2aWF0aWUgaGllcm9wIGVuIGt1bm5lbiBiZXRlciBpbiBlZW4gdGFiZWwgd29yZGVuIG9wZ2Vub21lbi4KCi0gWmUgbGF0ZW4gbmlldCB0b2Ugb20gYW5vbWFsaWXDq24gaW4gZGUgZGF0YSB6b2FscyBtZWV0Zm91dGVuIG9wIHRlIHNwb3Jlbi4KCi0gWmUgdmVyYnJ1aWtlbiB2ZWVsIHJ1aW10ZSwgYi52LiB2YW4gbnVsIHRvdCBkZSBrbGVpbnN0ZSB3YWFyZGUgdm9vciBkZSByZWxhdGlldmUgYWJ1bmRhbnRpZSkgd2FhciBnZWVuIGRhdGEgaW4gbGlndC4KCkhldCBpcyBiZXRlciBvbSBkZSBkYXRhIHpvIHJ1dyBtb2dlbGlqayB2b29yIHRlIHN0ZWxsZW4gem9kYXQgd2UgaW56aWNodCBrcmlqZ2VuIGluIGRlIHZlcmRlbGluZyB2YW4gZGUgZ2VnZXZlbnMuCkhpZXJ2b29yIHp1bGxlbiB3ZSBvbmRlcm1lZXIgYm94cGxvdHMgZ2VicnVpa2VuLgoKLS0tCgojIyMjIEJveHBsb3RzCgpgYGB7ciBmaWcuYWxpZ249J2NlbnRlcicsZWNobz1GQUxTRX0KZmVtIDwtIE5IQU5FUzo6TkhBTkVTICU+JSBmaWx0ZXIoR2VuZGVyPT0iZmVtYWxlIiAmICFpcy5uYShIZWlnaHQpICYgQWdlPjE4KSAlPiUgc2VsZWN0KEhlaWdodCkKYm94cGxvdChmZW0kSGVpZ2h0LCB5bGFiPSJsZW5ndGUgKGNtKSIsY2V4LmxhYj0xLjUsY2V4LmF4aXM9MS41LGNleC5tYWluPTEuNSkKcmFuZ2VMPC1xdWFudGlsZShmZW0kSGVpZ2h0LGMoLjI1LC43NSkpK2MoLTEsMSkqZGlmZihxdWFudGlsZShmZW0kSGVpZ2h0LGMoLjI1LC43NSkpKSoxLjUKYm94WXM8LWMocmFuZ2VMWzFdKyhtaW4oZmVtJEhlaWdodCktcmFuZ2VMWzFdKS8yLHJhbmdlKGZlbSRIZWlnaHRbZmVtJEhlaWdodDw9cmFuZ2VMWzJdJmZlbSRIZWlnaHQ+PXJhbmdlTFsxXV0pLHF1YW50aWxlKGZlbSRIZWlnaHQsYyguMjUsLjUsLjc1KSkscmFuZ2VMWzJdKyhtYXgoZmVtJEhlaWdodCktcmFuZ2VMWzJdKS8yKQp0ZXh0KGMoMC41LHJlcCgxLjMsNSksMC41KSxib3hZcyxsYWJlbHM9Yygib3V0bGllcnMiLCJ3aXNrZXIiLCJ3aXNrZXIiLCJ4MjUiLCJtZWRpYWFuIiwieDc1Iiwib3V0bGllcnMiKSxwb3M9NCxjZXg9MS4zKQpsaW5lcyhjKDAuOSwuNywwLjcsMC45KSxjKHJhbmdlTFsyXSxyYW5nZUxbMl0rKG1heChmZW0kSGVpZ2h0KS1yYW5nZUxbMl0pLzIscmFuZ2VMWzJdKyhtYXgoZmVtJEhlaWdodCktcmFuZ2VMWzJdKS8yLG1heChmZW0kSGVpZ2h0KSksbHR5PTIpCmxpbmVzKGMoMC45LC43LDAuNywwLjkpLGMocmFuZ2VMWzFdLHJhbmdlTFsxXSsobWluKGZlbSRIZWlnaHQpLXJhbmdlTFsxXSkvMixyYW5nZUxbMV0rKG1pbihmZW0kSGVpZ2h0KS1yYW5nZUxbMV0pLzIsbWluKGZlbSRIZWlnaHQpKSxsdHk9MikKYGBgCgotLS0KCldlIG1ha2VuIG51IGVlbiBib3hwbG90IHZvb3IgZGUgYXAgZGF0YQoKMS4gV2UgcGlwZW4gaGV0IGBhcGAgZGF0YWZyYW1lIG5hYXIgYGdncGxvdGAKMi4gV2Ugc2VsZWN0ZXJlbiBkZSBkYXRhIHZvb3IgZGUgcGxvdCB2aWEgYGdncGxvdChhZXMoeD10cnQseT1yZWwpKWAKMy4gV2Ugdm9lZ2VuIGxhYWcgdG9lIHZvb3IgZGUgYm94cGxvdCBkbXYgZGUgZnVuY3RpZSBgZ2VvbV9ib3hwbG90KClgCgpgYGB7cn0KYXAgJT4lICAKICBnZ3Bsb3QoYWVzKHg9dHJ0LHk9cmVsKSkgKwogIGdlb21fYm94cGxvdCgpCmBgYAoKCi0tLQoKTWVyayBvcCBkYXQgd2UgZGUgcGxvdCBvb2sgb3Aga3VubmVuIHNsYWFuIGFscyBlZW4gb2JqZWN0LgoKYGBge3J9CmFwQm94cGxvdCA8LSBhcCAlPiUgIAogIGdncGxvdChhZXMoeD10cnQseT1yZWwpKSArCiAgZ2VvbV9ib3hwbG90KCkKYGBgCgpEZSBwbG90IHdvcmR0IGRhbiBuaWV0IGdlbWFha3QuCgpPbSBkZSBwbG90IHdlZXIgdGUgZ2V2ZW4ga3VubmVuIHdlIGhldCBvYmplY3QgYWFucm9lcGVuCgpgYGB7cn0KYXBCb3hwbG90CmBgYAoKLS0tCgotIE1lcmsgb3AgZGF0IHdlIG5pZXQgem92ZWVsIGdlZ2V2ZW5zIGhlYmJlbi4gRW5rZWwgMTAgcGVyIGdyb2VwLgoKLSBIZXQgaXMgYWx0aWpkIGJldGVyIG9tIGRlIGRhdGEgem8gcnV3IG1vZ2VsaWprIHRlIHRvbmVuIQoKT21kYXQgZXIgbmlldCB6b3ZlZWwgZ2VnZXZlbnMgemlqbiBrdW5uZW4gd2UgZGUgZGF0YSB0b2V2b2VnZW4gYWFuIGRlIHBsb3Qgem9uZGVyIGRhdCBkaWUgdGUgZHJ1ayB3b3JkdC4KCi0gTWVyayBvcCBkYXQgd2UgaGV0IGFyZ3VtZW50IGBvdXRsaWVyLnNoYXBlYCBvcCBOQSAobm90IGF2YWlsYWJsZSkgemV0dGVuIGBvdXRsaWVyLnNoYXBlPU5BYCBpbiB0aGUgYGdlb21fYm94cGxvdGAgZnVuY3RpZSBvbWRhdCB3ZSBhbmRlcnMgb3V0bGllcnMgdHdlZSBrZWVyIHdlZXIgenVsbGVuIGdldmVuLiBFZXJzdCB2aWEgZGUgYm94cGxvdCBsYWFnIGVuIGRhYXJuYSBvbWRhdCB3ZSBlZW4gbGFhZyBtZXQgYWxsZSBydXdlIGRhdGEgdG9ldm9lZ2VuIGFhbiBkZSBwbG90LgotIFdlIGdldmVuIGRlIHJ1d2UgZGF0YSB3ZWVyIHZpYSBkZSAgYGdlb21fcG9pbnQocG9zaXRpb249ImppdHRlciIpYCBmdW5jdGllLiBXZSBnZWJydWlrZW4gaGllcmJpaiBoZXQgYXJndW1lbnQgcG9zaXRpb249J2ppdHRlcicgem9kYXQgd2Ugd2F0IHJhbmRvbSBydWlzIHRvZXZvZWdlbiBhYW4gZGUgeC1jb3JkaW5hYXQgem9kYXQgZGUgZ2VnZXZlbnMgZWxrYWFyIG5pZXQgb3ZlcmxhcHBlbi4KCmBgYHtyfQphcCAlPiUgIAogIGdncGxvdChhZXMoeD10cnQseT1yZWwpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGU9TkEpICsKICBnZW9tX3BvaW50KHBvc2l0aW9uPSJqaXR0ZXIiKQpgYGAKCkRpdCBpcyBlZW4gaW5mb3JtYXRpZXZlIHBsb3QhCgotLS0KCkFhbmdlemllbiB3ZSBkZSBwbG90IG9vayBoZWJiZW4gb3BnZXNsYWdlbiBrb25kZW4gd2UgZGl0IG9vayBkb2VuIGRvb3IgZGUgcGxvdCBvcCB0ZSByb2VwZW4gZW4gbm9nIGVlbiBsYWFnIHRvZSB0ZSB2b2VnZW4uCgpgYGB7cn0KYXBCb3hwbG90ICsKICBnZW9tX3BvaW50KHBvc2l0aW9uPSJqaXR0ZXIiKQpgYGAKCldlIGhhZGRlbiBoZXQgcmVzdWx0YWF0IG9vayBvcG5pZXV3IG9wIGt1bm5lbiBzbGFhbiB2b29yIGxhdGVyIGhlcmdlYnJ1aWsuCgpgYGB7cn0KYXBCb3hwbG90IDwtIGFwQm94cGxvdCArCiAgZ2VvbV9wb2ludChwb3NpdGlvbj0iaml0dGVyIikKYGBgCgotLS0KCi0gV2UgemFnZW4gZHVpZGVsaWprIGVlbiBlZmZlY3QgdmFuIGRlIHRyYW5zcGxhbnRhdGllIG9wIGRlIHJlbGF0aWV2ZSBhYnVuZGFudGllIHZhbiBTdGFwaHlsb2NvY2N1cy4KCi0gSXMgZGF0IGVmZmVjdCBudSBncm9vdCBnZW5vZWcgb20gdGUga3VubmVuIGNvbmNsdWRlcmVuIGRhdCBkZSBiZWhhbmRlbGluZyB3ZXJrdD8KCi0tLQoKYGBge3Igb3V0LndpZHRoPSc4MCUnLGZpZy5hc3A9LjgsIGZpZy5hbGlnbj0nY2VudGVyJyxlY2hvPUZBTFNFfQppZiAoInBpIiVpbiVscygpKSBybSgicGkiKQprb3B2b2V0ZXI8LWZ1bmN0aW9uKHgseSxhbmdsZT0wLGw9LjIsY2V4LmRvdD0uNSxwY2g9MTksY29sPSJibGFjayIpCnsKYW5nbGU9YW5nbGUvMTgwKnBpCnBvaW50cyh4LHksY2V4PWNleC5kb3QscGNoPXBjaCxjb2w9Y29sKQpsaW5lcyhjKHgseCtsKmNvcygtcGkvMithbmdsZSkpLGMoeSx5K2wqc2luKC1waS8yK2FuZ2xlKSksY29sPWNvbCkKbGluZXMoYyh4K2wvMipjb3MoLXBpLzIrYW5nbGUpLHgrbC8yKmNvcygtcGkvMithbmdsZSkrbC80KmNvcyhhbmdsZSkpLGMoeStsLzIqc2luKC1waS8yK2FuZ2xlKSx5K2wvMipzaW4oLXBpLzIrYW5nbGUpK2wvNCpzaW4oYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbC8yKmNvcygtcGkvMithbmdsZSkseCtsLzIqY29zKC1waS8yK2FuZ2xlKStsLzQqY29zKHBpK2FuZ2xlKSksYyh5K2wvMipzaW4oLXBpLzIrYW5nbGUpLHkrbC8yKnNpbigtcGkvMithbmdsZSkrbC80KnNpbihwaSthbmdsZSkpLGNvbD1jb2wpCmxpbmVzKGMoeCtsKmNvcygtcGkvMithbmdsZSkseCtsKmNvcygtcGkvMithbmdsZSkrbC8yKmNvcygtcGkvMitwaS80K2FuZ2xlKSksYyh5K2wqc2luKC1waS8yK2FuZ2xlKSx5K2wqc2luKC1waS8yK2FuZ2xlKStsLzIqc2luKC1waS8yK3BpLzQrYW5nbGUpKSxjb2w9Y29sKQpsaW5lcyhjKHgrbCpjb3MoLXBpLzIrYW5nbGUpLHgrbCpjb3MoLXBpLzIrYW5nbGUpK2wvMipjb3MoLXBpLzItcGkvNCthbmdsZSkpLGMoeStsKnNpbigtcGkvMithbmdsZSkseStsKnNpbigtcGkvMithbmdsZSkrbC8yKnNpbigtcGkvMi1waS80K2FuZ2xlKSksY29sPWNvbCkKfQoKcGFyKG1hcj1jKDAsMCwwLDApLG1haT1jKDAsMCwwLDApKQpwbG90KDAsMCx4bGFiPSIiLHlsYWI9IiIseGxpbT1jKDAsMTApLHlsaW09YygwLDEwKSxjb2w9MCx4YXh0PSJub25lIix5YXh0PSJub25lIixheGVzPUZBTFNFKQpyZWN0KDAsNiwxMCwxMCxib3JkZXI9InJlZCIsbHdkPTIpCnRleHQoLjUsOCwicG9wdWxhdGlvbiIsc3J0PTkwLGNvbD0icmVkIixjZXg9MikKc3ltYm9scyAoMywgOCwgY2lyY2xlcz0xLjUsIGNvbD0icmVkIixhZGQ9VFJVRSxmZz0icmVkIixpbmNoZXM9RkFMU0UsbHdkPTIpCnNldC5zZWVkKDMzMCkKZ3JpZD1zZXEoMCwxLjMsLjAxKQoKZm9yIChpIGluIDE6NTApCnsKCWFuZ2xlMT1ydW5pZihuPTEsbWluPTAsbWF4PTM2MCkKCWFuZ2xlMj1ydW5pZihuPTEsbWluPTAsbWF4PTM2MCkKCXJhZGl1cz1zYW1wbGUoZ3JpZCxwcm9iPWdyaWReMipwaS9zdW0oZ3JpZF4yKnBpKSxzaXplPTEpCglrb3B2b2V0ZXIoMytyYWRpdXMqY29zKGFuZ2xlMS8xODAqcGkpLDgrcmFkaXVzKnNpbihhbmdsZTEvMTgwKnBpKSxhbmdsZT1hbmdsZTIpCn0KdGV4dCg3LjUsOCwiTWljcm9iaW9tZSBpbiBwb3B1bGF0aW9uIixjb2w9InJlZCIsY2V4PTEuMikKCnJlY3QoMCwwLDEwLDQsYm9yZGVyPSJibHVlIixsd2Q9MikKdGV4dCguNSwyLCJzYW1wbGUiLHNydD05MCxjb2w9ImJsdWUiLGNleD0yKQpzeW1ib2xzICgzLCAyLCBjaXJjbGVzPTEuNSwgY29sPSJyZWQiLGFkZD1UUlVFLGZnPSJibHVlIixpbmNoZXM9RkFMU0UsbHdkPTIpCmZvciAoaSBpbiAwOjEpCglmb3IgKGogaW4gMDo0KQp7CgoJa29wdm9ldGVyKDIuMStqKigzLjktMi4xKS80LDEuMStpLzIsY29sPSJwdXJwbGUiKQp9CmZvciAoaSBpbiAyOjMpCglmb3IgKGogaW4gMDo0KQp7CgoJa29wdm9ldGVyKDIuMStqKigzLjktMi4xKS80LDEuNitpLzIsY29sPSJvcmFuZ2UiKQp9CnRleHQoNy41LDIsIk1pY3JvYmlvbWUgaW4gc2FtcGxlIixjb2w9ImJsdWUiLGNleD0xLjIpCgphcnJvd3MoMyw1LjksMyw0LjEsY29sPSJibGFjayIsbHdkPTMpCnRleHQoMS41LDUsIkVYUC4gREVTSUdOICgxKSIsY29sPSJibGFjayIsY2V4PTEuMikKdGV4dCg3LjUsLjUsIkRBVEEgRVhQTE9SQVRJT04gJlxuREVTQ1JJUFRJVkUgU1RBVElTVElDUyAoMikiLGNvbD0iYmxhY2siLGNleD0xLjIpCmFycm93cyg3LDQuMSw3LDUuOSxjb2w9ImJsYWNrIixsd2Q9MykKdGV4dCg4LjUsNSwiRVNUSU1BVElPTiAmXG5JTkZFUkVOQ0UgKDMpIixjb2w9ImJsYWNrIixjZXg9MS4yKQpgYGAKCi0tLQoKLSBJbmR1Y3RpZTogRG9vciBtaWRkZWwgdmFuIHN0YXRpc3Rpc2NoZSBiZXNsdWl0dm9ybWluZyAoaW5mZXJlbmNlKSBrdW5uZW4gd2UgdWl0c3ByYWtlbiBkb2VuIG92ZXIgZGUgcG9wdWxhdGllIG9wIGJhc2lzIHZhbiBlZW4gc3RlZWtwcm9lZi4KCi0gRGUgcHJpanMgZGllIHdlIGhpZXJ2b29yIGJldGFsZW4gaXMgb256ZWtlcmhlaWQhCgotIFdlIGt1bm5lbiBvcCBiYXNpcyB2YW4gZWVuIHN0ZWVrcHJvZWYgbm9vaXQgYWJzb2x1dXQgemVrZXIgemlqbiB2YW4gb256ZSBjb25jbHVzaWVzLgoKLS0tCgotIE1ldCBkYXRhIGt1bm5lbiB3ZSBuaWV0IGJld2lqemVuIGRhdCBlZW4gYmVoYW5kZWxpbmcgd2Vya3QuCgotIEZhbHNpZmljYXRpZSBwcmluY2lwZSB2YW4gUG9wcGVyOiBEYXRhIGt1bm5lbiBlbmtlbCBlZW4gaHlwb3RoZXNlIG9mIGVlbiB0aGVvcmllIG9udGtyYWNodGVuLgoKLSBNZXQgc3RhdGlzdGllayBrdW5uZW4gd2UgZHVzIG5pZXQgYWFudG9uZW4gZGF0IGRlIGJlaGFuZGVsaW5nIHdlcmt0LgoKLSBTdGF0aXN0aWVrIHphbCBvbnMgd2VsIHRvZWxhdGVuIG9tIGhldCBvbWdla2VlcmRlIHRlIGZhbHNpZmnDq3JlbjogYWxzIHdlIHZlcm9uZGVyc3RlbGxlbiBkYXQgZXIgZ2VlbiBlZmZlY3QgdmFuIGRlIGJlaGFuZGVsaW5nLCBzcHJlZWt0IGRlIGRhdGEgaW4gZGUgc3RlZWtwcm9lZiBkaXQgdGVnZW4/CgotIE1ldCBzdGF0aXN0aWVrIGt1bm5lbiB3ZSBiZXJla2VuZW4gaG9lIHdhYXJzY2hpam5saWprIGhldCBpcyBvbSBlZW4gZ2VtaWRkZWxkIHZlcnNjaGlsIGluIHJlbGF0aWV2ZSBhYnVuZGFudGllIHRlIHppZW4gdHVzc2VuIHBsYWNlYm8gZW4gdHJhbnNwbGFudGF0aWVncm9lcCBkYXQgbWluc3RlbnMgem8gZ3Jvb3QgaXMgYWxzIGluIGRlIHN0ZWVrcHJvZWYgYWxzIGRlIGJlaGFuZGVsaW5nIGdlZW4gZWZmZWN0IHpvdSBoZWJiZW4uCgotIERpZSBrYW5zIHdvcmR0IGVlbiBwLXdhYXJkZSBnZW5vZW1kLgoKLSBBbHMgcCBoZWVsIGtsZWluIGlzLCBkYW4gaXMgaGV0IGhlZWwgb253YWFyc2NoaWpubGlqayBvbSBlZW4gZGVyZ2VsaWprIGVmZmVjdCB0ZSBvYnNlcnZlcmVuIGluIGVlbiBzdGVla3Byb2VmIGRvb3IgdG9ldmFsLgoKLSBwIHdvcmR0IG1lZXN0YWwgdmVyZ2VsZWtlbiBtZXQgNSUuIEFscyBlciBnZWVuIGVmZmVjdCBpcyB2YW4gZGUgYmVoYW5kZWxpbmcgZGFuIHRvbGVyZXJlbiA1JSB2YWxzIHBvc2l0aWV2ZSBjb25jbHVzaWVzLgoKLSBPbSBkZSBrYW5zIHAgdGUgYmVyZWtlbmVuIGlzIGhldCBub2RpZyBvbSBkZSBkYXRhIHRlIG1vZGVsbGVyZW4gbWV0IHN0YXRpc3Rpc2NoZSBtb2RlbGxlbi4KCi0tLQoKSW4gbGF0ZXJlIGhvb2Zkc3R1a2tlbiB6dWxsZW4gd2UgemllbiBkYXQgd2UgdC10ZXN0IGt1bm5lbiBnZWJydWlrZW4gb20gaGV0Z2VlbiB3ZSBvYnNlcnZlcmVuIGluIGRlIG1pY3JvYmlvbWUgZGF0YXNldCB0ZSB2ZXJhbGdlbWVuZW4gbmFhciBkZSBwb3B1bGF0aWUuCgpgYGB7cn0KYXAgJT4lIHQudGVzdChyZWx+dHJ0LGRhdGE9LikKYGBgCgpDb25jbHVzaWU6CkdlbWlkZGVsZCBpcyBkZSByZWxhdGlldmUgYWJ1bmRhbnRpZSB2YW4gU3RhcGh5bG9jb2NjdXMgaW4gaGV0IG1pY3JvYmlvbWUgdmFuIHBlcnNvbmVuIG1ldCBlZW4gendlZXRnZXVyIGByIGZvcm1hdChhcFJlbFN1bSRtZWFuWzJdLWFwUmVsU3VtJG1lYW5bMV0sZGlnaXRzPTMpYCUgaG9nZXIgbmEgZGUgdHJhbnNwbGFudGllIGRhbiBuYSBkZSBwbGFjZWJvIGJlaGFuZGVsaW5nLgoKLS0tCgojIyBSYW5kb21pc2F0aWUKCi0gV2F0IHdvcmR0IHppam4gZGUgY29uc2VxdWVudGllcyB2YW4gaGV0IGdlYnJ1aWsgdmFuIGVlbiBzdGVla3Byb2VmIGVuIHZhbiByYW5kb21pc2F0aWU/CgotIFJhbmRvbWlzYXRpZSBpcyBzdGVyayBnZXJlbGF0ZWVyZCBtZXQgaGV0IGNvbmNlcHQgdmFuIGRlIHBvcHVsYXRpZSBlbiBzY29wZSB2YW4gZGUgc3R1ZGllLiAgCgotIERlIHNjb3BlIHZhbiBkZSBzdHVkaWUgbW9ldCBnb2VkIHdvcmRlbiBvbXNjaHJldmVuIHZvb3IgZGUgc3RhcnQgdmFuIGhldCBleHBlcmltZW50LgoKLSBPbWRhdCBkZSBzdGF0aXN0aXNjaGUgYW5hbHlzZSB2YWxpZGUgem91IHppam4gaXMgaGV0IG5vb2R6YWtlbGlqayBkYXQgZGUgc3ViamVjdGVuIHZvbGxlZGlnIHJhbmRvbSB3b3JkZW4gZ2V0cm9ra2VuIHVpdCBkZSBwb3B1bGF0aWUgbmFhciB3YWFyIHdlIG9uemUgY29uY2x1c2llcyB3ZW5zZW4gdGUgdmVyYWxnZW1lbmVuLgoKLSBWb2xsZWRpZyByYW5kb20gdHJla2tlbiB2YW4gZGUgcG9wdWxhdGllIGltcGxpY2VlcnQgZGF0OgoKICAgIC0gYWxsZSBzdWJqZWN0ZW4gdmFuIGRlIHBvcHVsYXRpZSBldmVudmVlbCBrYW5zIGhlYmJlbiBvbSBpbiBkZSBzdGVla3Byb2VmIHRlIHdvcmRlbiBvcGdlbm9tZW4KICAgIC0gZGUgc2VsZWN0aWUgdmFuIGVlbiBzdWJqZWN0IG9uYWZoYW5rZWxpamsgaXMgdmFuIGRlIGFuZGVyZSBzdWJqZWN0ZW4gaW4gZGUgc3RlZWtwcm9lZi4KCgotIERlIHN0ZWVrcHJvZWYgaXMgZGFuIHJlcHJlc2VudGF0aWVmIHZvb3IgZGUgcG9wdWxhdGllLCBtYWFyIGlzIG5vZyBzdGVlZHMgcmFuZG9tLgoKLSBXYXQgYmV0ZWtlbnQgZGl0PwoKLS0tCgojIFZhcmlhYmlsaXRlaXQgdmFuIHN0ZWVrcHJvZWYgdG90IHN0ZWVrcHJvZWYKCi0gT20gdGUgYmVncmlqcGVuIGRhdCBlZW4gc3RlZWtwcm9lZiByYW5kb20gaXMgem91ZGVuIHdlIGhldHplbGZkZSBleHBlcmltZW50IHZlZWwga2VlciBtb2V0ZW4ga3VubmVuIGhlcmhhbGVuIChgcmVwZWF0ZWQgc2FtcGxpbmdgKS4KCi0gRGFuIHpvdWRlbiB3ZSBpbnppY2h0IGt1bm5lbiBrcmlqZ2VuIGhvZSBkZSBnZWdldmVucyB2ZXJhbmRlcmVuIHZhbiBzdGVla3Byb2VmIHRvdCBzdGVla3Byb2VmLgoKLSBPbSBkaXQgdGUgaWxsdXN0cmVyZW4genVsbGVuIHdlIGdlYnJ1aWsgbWFrZW4gdmFuIGVlbiBoZWxlIGdyb3RlIHN0dWRpZS4KCi0gVWl0IGRpZSBzdHVkaWUgenVsbGVuIHdlIGRhbiBoZXJoYWFsZGVsaWprIGtsZWluZSBzdGVla3Byb2V2ZW4gdHJla2tlbiBvbSB0ZSBiZWdyaWpwZW4gaG9lIGRlIGdlZ2V2ZW5zIGVuIHN0YXRpc3RpZWtlbiB2ZXJhbmRlcmVuIHZhbiBzdGVla3Byb2VmIHRvdCBzdGVla3Byb2VmLiBPZiBvbSBtZXQgYW5kZXJlIHdvb3JkZW4gbmEgdGUgZ2FhbiB3YXQgZGUgdmFyaWFiaWxpdGVpdCBpcyB0dXNzZW4gc3RlZWtwcm9ldmVuLgoKLS0tCgpOYXRpb25hbCBIZWFsdGggQW5kIE51dHJpdGlvbiBFeGFtaW5hdGlvbiBTdHVkeSAoTkhBTkVTKQoKICAtIFNpbmRzIDE5NjAgd29yZGVuIGVsayBqYWFyIG1lbnNlbiB2YW4gYWxsZSBsZWVmdGlqZGVuIGdlw69udGVydmlld2QgYmlqIGhlbiB0aHVpcy4KICAtIEVyIG1hYWt0IG9vayBlZW4gZ2V6b25kaGVpZHNvbmRlcnpvZWsgZGVlbCB1aXQgdmFuIGRlIHN0dWR5IGRpZSBpbiBlZW4gbW9iaWVsIG9uZGVyem9la3NjZW50cnVtIHdvcmR0IGFmZ2Vub21lbi4KICAtIFdlIHp1bGxlbiBkZXplIGdyb3RlIHN0dWRpZSBnZWJydWlrZW4gb20gYXQgcmFuZG9tIHBlcnNvbmVuIHRlIHNlbGVjdGVyZW4gdmFuIGRlIEFtZXJpa2FhbnNlIHBvcHVsYXRpZS4KICAtIERhdCB6YWwgaW56aWNodCBnZXZlbiBpbiBob2UgZGUgZ2VnZXZlbnMgZW4gcmVzdWx0YXRlbiB2YW4gZWVuIGFuYWx5c2UgenVsbGVuIHZhcmnDq3JlbiB2YW4gc3RlZWtwcm9lZiB0b3Qgc3RlZWtwcm9lZi4KICAtIERlIGRhdGEgdmFuIGRlemUgc3R1ZGllIGlzIHRlcnVnIHRlIHZpbmRlbiBpbiBoZXQgUiBwYWtrZXQgYE5IQU5FU2AKCi0tLQoKYGBge3J9CmxpYnJhcnkoTkhBTkVTKQpoZWFkKE5IQU5FUykKZ2xpbXBzZShOSEFORVMpCmBgYAoKLS0tCgojIyBEYXRhIGV4cGxvcmF0aWUKCgoKT25kZXJ6b2Vrc3ZyYWFnOiBob2UgdmVyc2NoaWx0IGRlIGxlbmd0ZSB2YW4gdm9sd2Fzc2VuIG1hbm5lbiBlbiB2cm91d2VuLgoKMS4gV2UgcGlwZW4gZGUgZGF0YXNldCBuYWFyIGRlIGZ1bmN0aW9uIGBmaWx0ZXJgIG9tIGRlIGRhdGEgdGUgZmlsdGVyZW4gdm9sZ2VucyBsZWVmdGlqZC4gIAoyLiBXZSBwbG90dGVuIGRlIGxlbmd0ZSBtZXRpbmdlbi4KICAgIC0gV2Ugc2VsZWN0ZXJlbiBkZSBkYXRhIGRhdGEgbWV0IGhldCBjb21tYW5kbyBgZ2dwbG90KGFlcyh4PWxlbmd0ZSkpYAogICAgLSBXZSB2b2VnZW4gZWVuIGhpc3RvZ3JhbSB0b2UgbWV0IGhldCBjb21tYW5kbyBgZ2VvbV9oaXN0b2dyYW0oKWAKICAgIC0gV2UgbWFrZW4gdHdlZSB2ZXJ0aWthbGUgcGFuZWxzIG1ldCBoZXQgY29tbWFuZG8gYGZhY2V0X2dyaWQoR2VuZGVyfi4pYAogICAgLSBXZSB2ZXJhbmRlcmVuIGhldCBsYWJlbCB2YW4gZGUgeC1hcyBtZXQgZGUgYHhsYWJgIGZ1bmN0aWUuCgpgYGB7cn0KTkhBTkVTJT4lICAKICBmaWx0ZXIoQWdlID4gMTggJiAhaXMubmEoSGVpZ2h0KSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gSGVpZ2h0KSkrCiAgZ2VvbV9oaXN0b2dyYW0oKSArCiAgZmFjZXRfZ3JpZChHZW5kZXIgfiAuKSArCiAgeGxhYigiTGVuZ3RlIChjbSkiKQpgYGAKCi0tLQoKV2UgemllbiBkYXQgZGUgZGF0YSBudSBtaW4gb2YgbWVlciBzeW1tZXRyaXNjaCB2ZXJkZWVsZCB6aWpuIGVuIGVlbiBrbG9rdm9ybSBoZWJiZW4uICAKRGF0IHphbCBvbnMgdG9lIGxhdGVuIG9tIGRlIGRhdGEgdmVyZGVyIHNhbWVuIHRlIHZhdHRlbiBkb29yIGdlYnJ1aWsgdGUgbWFrZW4gdmFuIHR3ZWUgc3RhdGlzdGlla2VuOiBoZXQgZ2VtaWRkZWxkZSBlbiBkZSBzdGFuZGFhcmQgZGV2aWF0aWUgd2F0IGVlbiBtYWF0IGlzIHZvb3IgZGUgc3ByZWlkaW5nIHZhbiBkZSBnZWdldmVucyByb25kIGhldCBnZW1pZGRlbGRlLgoKLS0tCgpXZSBtYWtlbiBudSBlZW4gc3Vic2V0IHZhbiBkZSBkYXRhIGRpZSB3ZSB6dWxsZW4gZ2VicnVpa2VuIG9tIGFhbiB0ZSB0b25lbiBob2UgZGUgdmFyaWFiaWxpdGVpdCBpbiBrbGVpbmUgc3RlZWtwcm9ldmVuIGthbiB2YXJpw6tyZW4gdmFuIHN0ZWVrcHJvZWYgdG90IHN0ZWVrcHJvZWYuCgogIDEuIFdlIGZpbHRlcmVuIG9wIGxlZWZ0aWpkIGVuIHZlcndpamRlcmVuIG9udGJyZWtlbmRlbiBnZWdldmVucyAoTkEsIE5vdCBBdmFpbGFibGUpLgogIDIuIFdlIHNlbGVjdGVyZW4gZW5rZWwgaGV0IGdlc2xhY2h0IGVuIExlbmd0ZSB6b2RhdCBkZSBkYXRhc2V0IGdlZW4gb25ub2RpZ2UgdmFyaWFiZWxlbiBiZXZhdC4KCmBgYHtyfQpuaGFuZXNTdWIgPC0gTkhBTkVTICU+JQogIGZpbHRlcihBZ2UgPiAyNSAmICFpcy5uYShIZWlnaHQpKSAlPiUKICBzZWxlY3QoYygiR2VuZGVyIiwiSGVpZ2h0IikpCmBgYAoKLS0tCgpXZSBiZXJla2VuZW4gaGV0IGdlbWlkZGVsZGUgZW4gZGUgc3RhbmRhYXJkIGRldmlhdGllIHZvb3IgZGUgbGVuZ3RlIHZvb3IgbWFubmVuIGVuIHZyb3V3ZW4gaW4gZGUgZ3JvdGUgZGF0YXNldC4KV2UgZ3JvZXBlcmVuIGRlIGRhdGEgaGllcnZvb3Igb3AgYmFzaXMgdmFuIGhldCBnZXNsYWNodCAodmFyaWFibGUgR2VuZGVyKS4KCgpgYGB7cn0KCkhlaWdodFN1bSA8LSBuaGFuZXNTdWIgJT4lCiAgZ3JvdXBfYnkoR2VuZGVyKSAlPiUKICBzdW1tYXJpemVfYXQoIkhlaWdodCIsCiAgICAgICAgICAgICAgIGxpc3QobWVhbiA9IG1lYW4sCiAgICAgICAgICAgICAgIHNkID0gc2QpCiAgICAgICAgICAgICAgKQoKa25pdHI6OmthYmxlKAogIEhlaWdodFN1bSAlPiUKICBtdXRhdGVfaWYoaXMubnVtZXJpYywgcm91bmQsIGRpZ2l0cz0xKQogICkKYGBgCgotLS0KCiMjIEV4cGVyaW1lbnQKCi0gU3RlbCBkYXQgd2UgZ2VlbiB0b2VnYW5nIGhlYmJlbiB0b3QgZGUgbWV0aW5nZW4gdmFuIGRlIE5IQU5FUyBzdHVkaWUuCgotIFdlIHpvdWRlbiBkYW4gZWVuIGV4cGVyaW1lbnQgb3AgbW9ldGVuIHpldHRlbiBvbSBtZXRpbmdlbiBiaWogbWFubmVuIGVuIHZyb3V3ZW4gdGUgZG9lbi4KCi0gVmVyb25kZXJzdGVsIGRhdCB3ZSBidWRnZXQgaGViYmVuIG9tIG1ldGluZ2VuIGJpaiA1IG1hbm5lbiBlbiA1IHZyb3V3ZW4gdGUgZG9lbi4KCi0gV2Ugem91ZGVuIGRhbiA1IG1hbm5lbiBlbiA1IHZyb3V3ZW4gYm92ZW4gZGUgMjUgamFhciBhdCByYW5kb20gc2VsZWN0ZXJlbiB1aXQgZGUgQW1lcmlrYWFuc2UgcG9wdWxhdGllLgoKLSBXZSBrdW5uZW4gZGl0IGV4cGVyaW1lbnQgc2ltdWxlcmVuIGRvb3IgNSB2cm91d2VuIGVuIDUgbWFubmVuIGF0IHJhbmRvbSB0ZSBzZWxlY3RlcmVuIHVpdCBkZSBOSEFORVMgc3R1ZGllLgoKLS0tCgpgYGB7cn0Kc2V0LnNlZWQoMTAwMDAwMSkKblNhbXAgPC0gNQpmZW0gPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXI9PSJmZW1hbGUiKSAlPiUKICBzYW1wbGVfbihzaXplPTUpCgptYWwgPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXI9PSJtYWxlIikgJT4lCiAgc2FtcGxlX24oc2l6ZT01KQoKc2FtcDEgPC0gcmJpbmQoZmVtLG1hbCkKCnNhbXAxCmBgYAoKLS0tCgpEYXRhIEV4cGxvcmF0aWUKCmBgYHtyfQpzYW1wMSAlPiUKICBnZ3Bsb3QoYWVzKHg9SGVpZ2h0KSkgKwogIGdlb21faGlzdG9ncmFtKCkgKwogIGZhY2V0X2dyaWQoR2VuZGVyfi4pICsKICB4bGFiKCJMZW5ndGUgKGNtKSIpCgpIZWlnaHRTdW1FeHAxIDwtIHNhbXAxICU+JQogIGdyb3VwX2J5KEdlbmRlcikgJT4lCiAgc3VtbWFyaXplX2F0KCJIZWlnaHQiLAogICAgICAgICAgICAgICBsaXN0KG1lYW4gPSBtZWFuLAogICAgICAgICAgICAgICAgICAgICAgc2QgPSBzZCkKICAgICAgICAgICAgICAgICAgKQpIZWlnaHRTdW1FeHAxCmBgYAoKSGlzdG9ncmFtIGlzIG5pZXQgemludm9sIGFscyB3ZSBtYWFyIHpvIHdlaW5pZyBkYXRhcHVudGVuIGhlYmJlbi4KCi0tLQoKCkJveHBsb3QgaXMgYmV0ZXI6CgpgYGB7ciBlY2hvPUZBTFNFfQpzYW1wMSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBHZW5kZXIseSA9IEhlaWdodCkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKSArCiAgZ2VvbV9wb2ludChwb3NpdGlvbiA9ICJqaXR0ZXIiKSArCiAgZ2VvbV9wb2ludCgKICAgIGFlcyh4ID0gMSwgeSA9IEhlaWdodFN1bUV4cDEkbWVhblsxXSksCiAgICBzaXplID0gMywKICAgIHBjaCA9IDE3LAogICAgY29sb3I9ImRhcmtyZWQiKSArCiAgZ2VvbV9wb2ludCgKICAgIGFlcyh4ID0gMiwgeSA9IEhlaWdodFN1bUV4cDEkbWVhblsxXSksCiAgICBzaXplID0gMywKICAgIHBjaCA9IDE3LAogICAgY29sb3IgPSAiZGFya3JlZCIpICsKICB5bGFiKCJIZWlnaHQgKGNtKSIpCmBgYAoKLS0tCgpXZSB2b2VyZW4gaGllciBvb2sgZWVuIHQtdGVzdCB1aXQuCgpgYGB7cn0KdC50ZXN0KEhlaWdodH5HZW5kZXIsZGF0YT1zYW1wMSkKYGBgCgpJbiBoZXQgZXhwZXJpbWVudCB6aWpuIHZyb3V3ZW4gemlqbiBnZW1pZGRlbGQgYHIgcm91bmQoYWJzKEhlaWdodFN1bUV4cDEkbWVhblsxXS1IZWlnaHRTdW1FeHAxJG1lYW5bMl0pLDIpYCBjbSBgciBpZmVsc2UoSGVpZ2h0U3VtRXhwMSRtZWFuWzFdPkhlaWdodFN1bUV4cDEkbWVhblsyXSwiZ3JvdGVyIiwia2xlaW5lciIpYCBkYW4gbWFubmVuLiBFbiBhbHMgd2UgZWVuIHN0YXRpc3Rpc2NoZSB0ZXN0IHVpdHZvZXJlbiAoemllIGhvb2Zkc3R1ayA1OiBTdGF0aXN0aXNjaGUgYmVzbHVpdHZvcm1pbmcpIGt1bm5lbiB3ZSBiZXNsdWl0ZW4gZGF0IGRpdCB2ZXJzY2hpbCBzdGF0aXN0aXNjaCBgciBpZmVsc2UodC50ZXN0KEhlaWdodH5HZW5kZXIsc2FtcDEpJHAudmFsdWUgPCAwLjA1LCJzaWduaWZpY2FudCIsIm5pZXQgc2lnbmlmaWNhbnQiKWAgaXMuCgotLS0KCiMjIEhlcmhhYWwgaGV0IGV4cGVyaW1lbnQKCkFscyB3ZSBoZXQgZXhwZXJpbWVudCBoZXJoYWxlbiBzZWxlY3RlcmVuIHdlIGFuZGVyZSBtZW5zZW4gZW4gdmVya3JpamdlbiB3ZSBhbmRlcmUgcmVzdWx0YXRlbi4KCgpgYGB7cn0KZmVtIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyPT0iZmVtYWxlIikgJT4lCiAgc2FtcGxlX24oc2l6ZT01KQoKbWFsIDwtIG5oYW5lc1N1YiAlPiUKICBmaWx0ZXIoR2VuZGVyPT0ibWFsZSIpICU+JQogIHNhbXBsZV9uKHNpemU9NSkKCnNhbXAyIDwtIHJiaW5kKGZlbSxtYWwpCgpIZWlnaHRTdW1FeHAyIDwtIHNhbXAyICU+JQogIGdyb3VwX2J5KEdlbmRlcikgJT4lCiAgc3VtbWFyaXplX2F0KCJIZWlnaHQiLAogICAgICAgICAgICAgICBsaXN0KG1lYW49bWVhbiwKICAgICAgICAgICAgICAgICAgICBzZD1zZCkKICAgICAgICAgICAgICApCkhlaWdodFN1bUV4cDIKCnNhbXAyICU+JQogIGdncGxvdChhZXMoeCA9IEdlbmRlcix5ID0gSGVpZ2h0KSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEpICsKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gImppdHRlciIpICsKICBnZW9tX3BvaW50KAogICAgYWVzKHggPSAxLCB5ID0gSGVpZ2h0U3VtRXhwMSRtZWFuWzFdKSwKICAgIHNpemUgPSAzLAogICAgcGNoID0gMTcsCiAgICBjb2xvcj0iZGFya3JlZCIpICsKICBnZW9tX3BvaW50KAogICAgYWVzKHggPSAyLCB5ID0gSGVpZ2h0U3VtRXhwMSRtZWFuWzFdKSwKICAgIHNpemUgPSAzLAogICAgcGNoID0gMTcsCiAgICBjb2xvciA9ICJkYXJrcmVkIikgKwogIHlsYWIoIkhlaWdodCAoY20pIikKCnQudGVzdChIZWlnaHQgfiBHZW5kZXIsIGRhdGE9c2FtcDIpCmBgYAoKCkluIGRlIG5pZXV3ZSBzdGVla3Byb2VmIHppam4gdnJvdXdlbiB6aWpuIGdlbWlkZGVsZCBgciByb3VuZChhYnMoSGVpZ2h0U3VtRXhwMiRtZWFuWzFdLUhlaWdodFN1bUV4cDIkbWVhblsyXSksMilgIGNtIGByIGlmZWxzZShIZWlnaHRTdW1FeHAyJG1lYW5bMV0+SGVpZ2h0U3VtRXhwMiRtZWFuWzJdLCJncm90ZXIiLCJrbGVpbmVyIilgIGRhbiBtYW5uZW4uIEVuIGRpdCB2ZXJzY2hpbCBpcyBzdGF0aXN0aXNjaCBgciBpZmVsc2UodC50ZXN0KEhlaWdodH5HZW5kZXIsc2FtcDIsdmFyLmVxdWFsPVRSVUUpJHAudmFsdWUgPCAwLjA1LCJzaWduaWZpY2FudCIsIm5pZXQgc2lnbmlmaWNhbnQiKWAKCgotLS0KCiMjIEhlcmhhYWwgaGV0IGV4cGVyaW1lbnQgb3BuaWV1dwoKYGBge3J9CnNlZWQgPC0gMTMzNjYwMgpmZW0gPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXI9PSJmZW1hbGUiKSAlPiUKICBzYW1wbGVfbihzaXplPTUpCgptYWwgPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXI9PSJtYWxlIikgJT4lCiAgc2FtcGxlX24oc2l6ZT01KQoKc2FtcDMgPC0gcmJpbmQoZmVtLG1hbCkKCkhlaWdodFN1bUV4cDMgPC0gc2FtcDMgJT4lCiAgZ3JvdXBfYnkoR2VuZGVyKSAlPiUKICBzdW1tYXJpemVfYXQoIkhlaWdodCIsCiAgICAgICAgICAgICAgIGxpc3QobWVhbj1tZWFuLAogICAgICAgICAgICAgICAgICAgIHNkPXNkKQogICAgICAgICAgICAgICkKSGVpZ2h0U3VtRXhwMwoKc2FtcDMgJT4lCiAgZ2dwbG90KGFlcyh4ID0gR2VuZGVyLHkgPSBIZWlnaHQpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSkgKwogIGdlb21fcG9pbnQocG9zaXRpb24gPSAiaml0dGVyIikgKwogIGdlb21fcG9pbnQoCiAgICBhZXMoeCA9IDEsIHkgPSBIZWlnaHRTdW1FeHAxJG1lYW5bMV0pLAogICAgc2l6ZSA9IDMsCiAgICBwY2ggPSAxNywKICAgIGNvbG9yPSJkYXJrcmVkIikgKwogIGdlb21fcG9pbnQoCiAgICBhZXMoeCA9IDIsIHkgPSBIZWlnaHRTdW1FeHAxJG1lYW5bMV0pLAogICAgc2l6ZSA9IDMsCiAgICBwY2ggPSAxNywKICAgIGNvbG9yID0gImRhcmtyZWQiKSArCiAgeWxhYigiSGVpZ2h0IChjbSkiKQoKdC50ZXN0KEhlaWdodCB+IEdlbmRlciwgZGF0YT1zYW1wMykKYGBgCgpJbiBkZSBuaWV1d2Ugc3RlZWtwcm9lZiB6aWpuIHZyb3V3ZW4gZ2VtaWRkZWxkIGByIHJvdW5kKGFicyhIZWlnaHRTdW1FeHAzJG1lYW5bMV0tSGVpZ2h0U3VtRXhwMyRtZWFuWzJdKSwyKWAgY20gYHIgaWZlbHNlKEhlaWdodFN1bUV4cDMkbWVhblsxXT5IZWlnaHRTdW1FeHAzJG1lYW5bMl0sImdyb3RlciIsImtsZWluZXIiKWAgZGFuIG1hbm5lbi4gRW4gZGl0IHZlcnNjaGlsIGlzIHN0YXRpc3Rpc2NoIGByIGlmZWxzZSh0LnRlc3QoSGVpZ2h0fkdlbmRlcixzYW1wMyx2YXIuZXF1YWw9VFJVRSkkcC52YWx1ZSA8IDAuMDUsInNpZ25pZmljYW50IiwibmlldCBzaWduaWZpY2FudCIpYAoKLS0tCgojIyBTYW1lbnZhdHRpbmcKCi0gV2UgdHJva2tlbiBhdCByYW5kb20gYW5kZXJlIHByb2VmcGVyc29uZW4gaW4gZWxrZSBzdGVla3Byb2VmCgotIEhpZXJkb29yIHZlcnNjaGlsbGVuIGxlbmd0ZW1ldGluZ2VuIHZhbiBzdGVla3Byb2VmIHRvdCBzdGVla3Byb2VmLgoKLSBEdXMgb29rIGRlIGdlc2NoYXR0ZSBnZW1pZGRlbGRlcyBlbiBzdGFuZGFhcmQgZGV2aWF0aWVzLgoKLSBCaWpnZXZvbGcgemlqbiBvbnplIGNvbmNsdXNpZXMgb29rIG9uemVrZXIgZW4ga3VubmVuIGRlemUgd2lqemlnZW4gdmFuIHN0ZWVrcHJvZWYgdG90IHN0ZWVrcHJvZWYuCgotIFN0ZWVrcHJvZXZlbiB3YWFyYmlqIGhldCBlZmZlY3QgdGVnZW5nZXN0ZWxkIGlzIGFhbiBkYXQgaW4gZGUgcG9wdWxhdGllIGVuIHdhYXJiaWogd2UgYmVzbHVpdGVuIGRhdCBoZXQgdmVyc2NoaWwgc2lnbmlmaWNhbnQgaXMsIHppam4gemVsZHphYW0uCgokXHJpZ2h0YXJyb3ckIE1ldCBzdGF0aXN0aWVrIGNvbnRyb2xlcmVuIHdlIGRlIGthbnMgb3AgaGV0IHRyZWtrZW4gZm91dGUgY29uY2x1c2llcy4KCi0gRGl0IHdvcmR0IGluIGRlIG9uZGVyc3RhYW5kZSBjb2RlIGdlw69sbHVzdHJlZXJkLiBXZSB0cmVra2VuIDEwMDAwIGhlcmhhYWxkZSBzdGVla3Byb2V2ZW4gdmFuIDUgdnJvdXdlbiBlbiA1IG1hbm5lbiB1aXQgZGUgTkhBTkVTIHN0dWRpZS4KCmBgYHtyfQojIEFhbnRhbCBzaW11bGF0aWVzIGVuIHN0ZWVrcHJvZWZncm9vdHRlIHBlciBncm9lcApuU2ltIDwtIDEwMDAwCm5TYW1wIDwtIDUKCiMgV2UgZmlsdGVyZW4gZGUgZGF0YSB2b29yYWYgem9kYXQgd2UgZGl0IG5pZXQgdGVsa2VucyBvcG5pZXV3IGhvZXZlbiB0ZSBkb2VuCmZlbSA8LSBuaGFuZXNTdWIgJT4lCiAgZmlsdGVyKEdlbmRlciA9PSAiZmVtYWxlIikKCm1hbCA8LSBuaGFuZXNTdWIgJT4lCiAgZmlsdGVyKEdlbmRlciA9PSAibWFsZSIpCgojIFNpbXVsYXRpZSBzdHVkaWUKIyBPbSBzbmVsbGUgZnVuY3RpZXMgdGUga3VubmVuIGdlYnJ1aWtlbiBuZW1lbiB3ZSBlZXJzdCBuU2ltIHN0ZWVrcHJvZXZlbiBlbiBiZXJla2VuZW4gd2UgZGFhcm5hIGFsbGVzLgoKZmVtU2FtcHMgPC0gbWFsU2FtcHMgPC1tYXRyaXgoTkEsIG5yb3c9blNhbXAsIG5jb2w9blNpbSkKZm9yIChpIGluIDE6blNpbSkKewogIGZlbVNhbXBzWyxpXSA8LSBzYW1wbGUoZmVtJEhlaWdodCwgblNhbXApCiAgbWFsU2FtcHNbLGldIDwtIHNhbXBsZShtYWwkSGVpZ2h0LCBuU2FtcCkKfQoKcmVzIDwtIGRhdGEuZnJhbWUoCiAgdmVyc2NoaWw9Y29sTWVhbnMoZmVtU2FtcHMpIC0gY29sTWVhbnMobWFsU2FtcHMpLAogIFJmYXN0Ojp0dGVzdHMoZmVtU2FtcHMsIG1hbFNhbXBzKQogICkKCnN1bShyZXMkcHZhbHVlIDwgMC4wNSAmIHJlcyR2ZXJzY2hpbCA8IDApCnN1bShyZXMkcHZhbHVlID49IDAuMDUpCnN1bShyZXMkcHZhbHVlIDwgMC4wNSAmIHJlcyR2ZXJzY2hpbD4wKQoKcmVzICU+JQogIGdncGxvdChhZXMoeD12ZXJzY2hpbCx5PS1sb2cxMChwdmFsdWUpLGNvbG9yPXB2YWx1ZSA8IDAuMDUpKSArCiAgZ2VvbV9wb2ludCgpICsKICB4bGFiKCJHZW1pZGRlbGQgVmVyc2NoaWwgKGNtKSIpICsKICB5bGFiKCJTdGF0aXN0aXNjaGUgU2lnbmlmaWNhbnRpZSAoLWxvZzEwIHApIikKCnJlcyAlPiUKICBnZ3Bsb3QoYWVzKHkgPSB2ZXJzY2hpbCkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgeWxhYigiR2VtaWRkZWxkIFZlcnNjaGlsIChjbSkiKQogIHhsYWIoIiIpCmBgYAoKT3AgYmFzaXMgdmFuIDEwIDAwMCBzdGVla3Byb2V2ZW4gdmFuIDUgbWFubmVuIGVuIDUgdnJvdXdlbiB6YWdlbiB3ZSBkYXQgaW4gYHIgc3VtKHJlcyRwdmFsdWU8MC4wNSZyZXMkdmVyc2NoaWw8MClgIHN0ZWVrcHJvZXZlbiB2cm91d2VuIGdlbWlkZGVsZCBzaWduaWZpY2FudCBrbGVpbmVyIHppam4gZGFuIG1hbm5lbi4gSW4gYHIgc3VtKHJlcyRwdmFsdWU+PTAuMDUpYCBzdGVla3Byb2V2ZW4gYmVzbHVpdGVuIHdlIGRhdCB2cm91d2VuIGVuIG1hbm5lbiBnZW1pZGRlbGQgbmlldCBzaWduaWZpY2FudCB2ZXJzY2hpbGxlbiBpbiBsZW5ndGUuIEVuIGluIGByIHN1bShyZXMkcHZhbHVlPDAuMDUmcmVzJHZlcnNjaGlsPjApYCBiZXNsdWl0ZW4gd2UgZGF0IHZyb3V3ZW4gZ2VtaWRkZWxkIHNpZ25pZmljYW50IGdyb3RlciB6aWpuIGRhbiBtYW5uZW4uCgotIERlIHN0ZWVrcHJvZWYgZGllIHdlIHRvb25kZW4gd2FhcnVpdCB3ZSB6b3VkZW4gYmVzbHVpdGVuIGRhdCB2cm91d2VuIHNpZ25pZmljYW50IGdyb3RlciB6aWpuIGRhbiBtYW5uZW4gaXMgaGVlbCBvbndhYXJzY2hpam5saWprLiBFciBtb2VzdGVuIGByIHBhc3RlKHNlZWQpYCBzdGVla3Byb2V2ZW4gd29yZGVuIGdldHJva2tlbiBvbSBkZXplIGV4dHJlbWUgc3RlZWtwcm9lZiB0ZSB2aW5kZW4uCgpIZXQgZmVpdCBkYXQgd2UgaW4gdmVlbCBzdGVla3Byb2V2ZW4gcmVzdWx0YXRlbiB2aW5kZW4gZGllIHN0YXRpc3Rpc2NoIG5pZXQgc2lnbmlmaWNhbnQgemlqbiBrb210IG9tZGF0IGRlIHN0YXRpc3Rpc2NoZSB0b2V0cyBlZW4gdGUgbGFnZSBrcmFjaHQgaGVlZnQgb20gaGV0IHZlcnNjaGlsIHRlIGRldGVjdGVyZW4gd2FubmVlciBlciBtYWFyIDUgb2JzZXJ2YXRpZXMgemlqbiBwZXIgZ3JvZXAuCgotLS0KCiMjIEdyb3RlcmUgc3RlZWtwcm9lZj8KCldhdCBnZWJldXJ0IGVyIGFscyB3ZSBkZSBzdGVla3Byb2VmIHZlcmhvZ2VuIG5hYXIgNTAgb2JzZXJ2YXRpZXMgcGVyIGdyb2VwPwoKCmBgYHtyfQojIEFhbnRhbCBzaW11bGF0aWVzIGVuIHN0ZWVrcHJvZWZncm9vdHRlIHBlciBncm9lcApuU2ltIDwtIDEwMDAwCm5TYW1wIDwtIDUwCgojIFdlIGZpbHRlcmVuIGRlIGRhdGEgdm9vcmFmIHpvZGF0IHdlIGRpdCBuaWV0IHRlbGtlbnMgb3BuaWV1dyBob2V2ZW4gdGUgZG9lbgpmZW0gPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXIgPT0gImZlbWFsZSIpCgptYWwgPC0gbmhhbmVzU3ViICU+JQogIGZpbHRlcihHZW5kZXIgPT0gIm1hbGUiKQoKIyBTaW11bGF0aWUgc3R1ZGllCiMgT20gc25lbGxlIGZ1bmN0aWVzIHRlIGt1bm5lbiBnZWJydWlrZW4gbmVtZW4gd2UgZWVyc3QgblNpbSBzdGVla3Byb2V2ZW4gZW4gYmVyZWtlbmVuIHdlIGRhYXJuYSBhbGxlcy4KCmZlbVNhbXBzIDwtIG1hbFNhbXBzIDwtIG1hdHJpeChOQSwgbnJvdyA9IG5TYW1wLCBuY29sID0gblNpbSkKZm9yIChpIGluIDE6blNpbSkKewogIGZlbVNhbXBzWyxpXSA8LSBzYW1wbGUoZmVtJEhlaWdodCwgblNhbXApCiAgbWFsU2FtcHNbLGldIDwtIHNhbXBsZShtYWwkSGVpZ2h0LCBuU2FtcCkKfQoKcmVzIDwtIGRhdGEuZnJhbWUoCiAgdmVyc2NoaWwgPSBjb2xNZWFucyhmZW1TYW1wcykgLSBjb2xNZWFucyhtYWxTYW1wcyksCiAgUmZhc3Q6OnR0ZXN0cyhmZW1TYW1wcywgbWFsU2FtcHMpCiAgKQoKc3VtKHJlcyRwdmFsdWUgPCAwLjA1ICYgcmVzJHZlcnNjaGlsIDwgMCkKc3VtKHJlcyRwdmFsdWUgPj0gMC4wNSkKc3VtKHJlcyRwdmFsdWUgPCAwLjA1ICYgcmVzJHZlcnNjaGlsID4gMCkKCnJlcyAlPiUKICBnZ3Bsb3QoYWVzKHg9dmVyc2NoaWwseT0tbG9nMTAocHZhbHVlKSxjb2xvcj1wdmFsdWU8MC4wNSkpICsKICBnZW9tX3BvaW50KCkgKwogIHhsYWIoIkdlbWlkZGVsZCBWZXJzY2hpbCAoY20pIikgKwogIHlsYWIoIlN0YXRpc3Rpc2NoZSBTaWduaWZpY2FudGllICgtbG9nMTAgcCkiKQoKcmVzICU+JQogIGdncGxvdChhZXMoeT12ZXJzY2hpbCkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgeWxhYigiR2VtaWRkZWxkIFZlcnNjaGlsIChjbSkiKQogIHhsYWIoIiIpCmBgYAoKLS0tCgojIFNhbGsgU3R1ZHkKCi0gSW4gMTkxNiwgYnJhayBkZSBlZXJzdGUgZ3JvdGUgcG9saW8gZXBpZGVtaWUgdWl0IGluIGRlIFVTQS4KLSBCZWdpbiBkZSBqYXJlbiA1MCBvbnR3aWtrZWxkZSBKb2huIFNhbGsgZWVuIHZhY2NpbiBtZXQgYmVsb3ZlbmRlIHJlc3VsdGF0ZW4gaW4gaGV0IGxhYi4KLSBJbiAxOTU0LCBoZWVmdCBkZSBOYXRpb25hbCBGb3VuZGF0aW9uCmZvciBJbmZhbnRpbGUgUGFyYWx5c2lzIChORklQKSBlZW4gZ3JvdGUgc3R1ZGllIG9wZ2V6ZXQgb20gZGUgZWZmZWN0aXZpdGVpdCB2YW4gaGV0IFNhbGsgdmFjY2luIG5hIHRlIGdhYW4uCi0gVmVyb25kZXJzdGVsIGRhdCBkZSBORklQIGluIDE5NTQgZWVuIGdyb290IGFhbnRhbCBraW5kZXJlbiB6b3UgaGViYmVuIGdldmFjY2luZWVyZCwgd2F0IHpvdWRlbiB6ZSBkYW4ga3VubmVuIGJlc2x1aXRlbiBhbHMgZGUgcG9saW8gaW5jaWRlbnRpZSBpbiAxOTU0IGxhZ2VyIHdhcyBkYW4gaW4gMTk1Mz8KCi0tLQoKIyMgTkZJUCBTdHVkeQojIyMgRGVzaWduCgotIEdyb3RlIHNpbXVsdGFuZSBzdHVkaWUgbWV0IGdldmFjY2luZWVyZGUga2luZGVyZW4gKGNhc2VzKSBlbiBvbmdldmFjY2luZWVyZGUga2luZGVyZW4gKGNvbnRyb2xlcykuCi0gSW4gc2Nob2xlbiB2YW4gZGlzdHJpY3RlbiBtZXQgaG9nZSBwb2xpbyBpbmNpZGVudGllLgotIENhc2VzOiBraW5kZXJlbiB2YW4gZGUgdHdlZWRlIGdyYWFkIHZhbiBoZXQgbGFnZXIgb25kZXJ3aWpzIHdhYXJ2YW4gZGUgb3VkZXJzIHRvZXN0ZW1kZW4gbWV0IHZhY2NpbmF0aWUuCi0gQ29udHJvbGVzOiBraW5kZXJlbiB2YW4gZGUgZWVyc3RlIGVuIGRlcmRlIGdyYWFkLgoKIyMjIERhdGEKYGBge3J9Cm5maXAgPC0gdGliYmxlKAogIGdyb3VwPWMoImNhc2VzIiwiY29udHJvbHMiLCJub0NvbmNlbnQiKSwKICBncmFkZT1jKCJnMiIsImcxZzMiLCJnMiIpLAogIHZhY2Npbj1jKCJ5ZXMiLCJubyIsIm5vIiksCiAgdG90YWw9YygyMjE5OTgsNzI1MTczLDEyMzYwNSksCiAgcG9saW89Yyg1NCwzOTEsNTYpCiAgKSAlPiUKICBtdXRhdGUobm9Qb2xpbyA9IHRvdGFsIC0gcG9saW8pCmtuaXRyOjprYWJsZShuZmlwKQpgYGAKClZlcmdlbGlqayBkZSBwb2xpbyBpbmNpZGVudGllPwoKLS0tCgpgYGB7cn0KbmZpcCA8LSBuZmlwICU+JQogIG11dGF0ZShpbmNpZGVuY2VQTSA9IHJvdW5kKG5maXAkcG9saW8vbmZpcCR0b3RhbCoxZTYsMCkpCmtuaXRyOjprYWJsZShuZmlwKQpgYGAKCldhdCBrdW5uZW4gd2UgY29uY2x1ZGVyZW4/CgotLS0KCiMjIENvbmZvdW5kaW5nCgoKYGBge3IsZWNobz1GQUxTRSwgZmlnLmFsaWduID0gImNlbnRlciIsb3V0LndpZHRoID0gJzUwJSd9CnBsb3QoYygwLDAsMSksYygtMiwyLDApLHBjaD1jKCJTIiwiViIsIlAiKSx4YXh0PSJub25lIix5YXh0PSJub25lIixheGVzPUZBTFNFLHhsYWI9IiIseWxhYj0iIixjZXg9NCx5bGltPWMoLTIuMiwyLjIpKQphcnJvd3MoeDA9MC4xLHgxPS45LHkwPTEuOCx5MT0wLjEsbHdkPTQpCmFycm93cyh4MD0wLjEseDE9LjkseTA9LTEuOCx5MT0tMC4yLGx3ZD00KQphcnJvd3MoeDA9MCx4MT0wLHkwPS0xLjQseTE9MS40LGx3ZD00KQpgYGAKCgotIFdlIG9ic2VydmVyZW4gZWVuIGxhZ2VyZSBwb2xpbyAoUCkgaW5jaWRlbnRpZSB2b29yIGtpbmRlcmVuIGJpaiB3aWUgZGUgb3VkZXJzIGdlZW4gdG9lc3RlbW1pbmcgZ2F2ZW4gZGFuIGluIGRlIGNvbnRyb2xlIGdyb2VwLiAgCgotIFRvZXN0ZW1taW5nIHZvb3IgdmFjY2luYXRpZSAoVikgaXMgZ2Vhc3NvY2llZXJkIG1ldCBkZSBzb2Npby1lY29ub21pc2NoZSBzdGF0dXMgKFMpLgoKLSBLaW5kZXJlbiB2YW4gbGFnZXJlIHNvY2lvLWVjb25vbWlzY2hlIHN0YXR1cyB6aWpuIG1lZXIgcmVzaXN0ZW50IHRlZ2VuIGRlIHppZWt0ZS4KCi0gRGUgZ3JvZXBlbiB2YW4gY2FzZXMgZW4gY29udHJvbGVzIHppam4gbmlldCB2ZXJnZWxpamtiYWFyCiAgICAtIHZlcnNjaGlsIGluIGxlZWZ0aWpkCiAgICAtIHZlcnNjaGlsIGluIHNvY2lvLWVjb25vbWlzY2hlIHN0YXR1cyBlbgogICAgLSB2ZXJzY2hpbCBpbiB2YXRiYWFyaGVpZCB2b29yIGRlIHppZWt0ZS4KCi0tLQoKIyMgU2FsayBTdHVkeQoKIyMjIERlc2lnbgpFZW4gbmlldXdlIHN0dWRpZSB3ZXJkIHVpdGdldm9lcmQ6IGR1YmJlbCBibGluZGUgZ2VyYW5kb21pc2VlcmRlIHN0dWRpZS4KCiAgLSBLaW5kZXJlbiB3b3JkZW4gYXQgcmFuZG9tIHRvZWdld2V6ZW4gYWFuIGNvbnRyb2xlIG9mIGNhc2UgYXJtIHZhbiBoZXQgZXhwZXJpbWVudCBuYWRhdCBkZSBvdWRlcnMgdG9lc3RlbWRlbiBtZXQgdmFjY2luYXRpZS4KICAtIENvbnRyb2xlOiB2YWNjaW5hdGllIG1ldCBwbGFjZWJvCiAgLSBUcmVhdG1lbnQ6IHZhY2NpbmF0aWUgbWV0IHZhY2NpbgogIC0gRG91YmxlIGJsaW5kaW5nOgogICAgLSBvdWRlcnMgZW4ga2luZGVyZW4gd2V0ZW4gbmlldCBvZiB6ZSB3ZXJkZW4gZ2V2YWNjaW5lZXJkIG9mIG5pZXQKICAgIC0gbWVkaXNjaGUgc3RhZiBlbiBvbmRlcnpvZWtlcnMgd2V0ZW4gbmlldCBvZiBoZXQga2luZCBoZXQgdmFjY2luIG9mIGRlIHBsYWNlYm8ga3JlZWcKCi0tLQoKIyMjIERhdGEKCmBgYHtyfQpzYWxrIDwtIGRhdGEuZnJhbWUoCiAgZ3JvdXA9YygiY2FzZXMiLCJjb250cm9sIiwibm9Db25jZW50IiksCiAgdHJlYXRtZW50PWMoInZhY2NpbmUiLCJwbGFjZWJvIiwibm9uZSIpLAogIHRvdGFsPWMoMjAwNzQ1LDIwMTIyOSwgMzM4Nzc4KSxwb2xpbz1jKDU3LDE0MiwxNTcpCiAgKSAlPiUKICBtdXRhdGUoCiAgICBub1BvbGlvID0gdG90YWwtcG9saW8sCiAgICBpbmNpZGVuY2VQTSA9IHJvdW5kKHBvbGlvL3RvdGFsKjFlNiwwKQogICAgKQprbml0cjo6a2FibGUoc2FsaykKYGBgCgotIFdlIG9ic2VydmVyZW4gZWVuIHZlZWwgZ3JvdGVyIGVmZmVjdCBudSBkYXQgY2FzZXMgZW4gY29udHJvbGVzIHZlcmdlbGlqa2JhYXIgemlqbiwgaW5jaWRlbnRpZSB2YW4gcmVzcGVjdGlldmVsaWprIGByIHNhbGskaW5jaWRlbmNlUE1bMV1gICBhbmQgYHIgc2FsayRpbmNpZGVuY2VQTVsyXWAgcGVyIG1pbGpvZW4uCgotIERlIHBvbGlvIGluY2lkZW50aWUgdm9vciBraW5kZXJlbiBkaWUgZ2VlbiB0b2VzdGVtbWluZyBnZXZlbiBibGlqZnQgdmVyZ2VsaWprYmFhciAgYHIgbmZpcCRpbmNpZGVuY2VQTVszXWAgYW5kIGByIHNhbGskaW5jaWRlbmNlUE1bM11gIHBlciBtaWxqb2VuIHJlc3BlY3RpZXZlbGlqayBpbiB0aGUgTkZJUCBhbmQgU2FsayBzdHVkeS4KCi0tLQoKIyBSb2wgdmFuIFN0YXRpc3RpZWsKCi0gV2UgaGViYmVuIGdlemllbiBkYXQKICAgIC0gaGV0IGJlbGFuZ3JpamsgaXMgb20gZGUgc2NvcGUgdmFuIGRlIHN0dWRpZSBnb2VkIHRlIHNwZWNpZmnDq3JlbiB2b29yIGRlIHN0YXJ0IHZhbiBoZXQgZXhwZXJpbWVudAogICAgLSByYW5kb21pc2F0aWUgbm9kaWcgaXMgb20gZWVuIHJlcHJlc2VudGF0aWV2ZSBzdGVla3Byb2VmIHRlIG5lbWVuCiAgICAtIHN0ZWVrcHJvZWYgZ3Jvb3R0ZSBpcyBoZWVsIGJlbGFuZ3JpamsKICAgIC0gd2UgbW9ldGVuIG9ucyBiZXd1c3QgemlqbiB2YW4gQ29uZm91bmRpbmcKICAgIC0gZWVuIGdvZWRlIGNvbnRyb2xlIGlzIGJlbGFuZ3JpamsKCgokXHJpZ2h0YXJyb3ckIEdvZWRlIHByb2Vmb3B6ZXQgaXMgY3J1Y2lhYWwhCgotLS0KCi0gV2UgaGViYmVuIG9vayBnZW9ic2VydmVlcmQgZGF0IGVyIHZhcmlhYmlsaXRlaXQgaXMgaW4gZGUgcG9wdWxhdGllCi0gV2Uga3VubmVuIG1hYXIgZWVuIGJlcGVya3RlIHN0ZWVrcHJvZWYgbmVtZW4gdWl0IGRlIHBvcHVsYXRpZQoKJFxyaWdodGFycm93JCBvbnpla2VyaGVpZCBpbiBkZSByZXN1bHRhdGVuCiRccmlnaHRhcnJvdyQgb256ZWtlcmhlaWQgaW4gZGUgY29uY2x1c2llcwoKCi0tLQoKLSBTdGF0aXN0aWVrIGlzIGRlIHdldGVuc2NoYXAgdm9vciBoZXQKICAgIDEuIHZlcnphbWVsZW4gKGV4cGVyaW1lbnRlZWwgZGVzaWduKSwKICAgIDIuIGV4cGxvcmVuIChkYXRhIGV4cGxvcmF0aW9uKSBlbgogICAgMy4gbGVyZW4gdmFuIGRhdGEgem9kYXQgd2UgaGV0Z2VlbiB3ZSBvYnNlcnZlcmVuIGluIGRlIHN0ZWVrcHJvZWYgem91ZGVuIGt1bm5lbiB2ZXJhbGdlbWVuZW4gbmFhciBkZSBwb3B1bGF0aWUgdGVyd2lqbCB3ZSBkZSBvbnpla2VyaGVpZCBxdWFudGlmaWNlcmVuLCBjb250cm9sZXJlbiBlbiByYXBwb3J0ZXJlbiAoc3RhdGlzdGlzY2ggbW9kZWxsZXJlbiBlbiBzdGF0aXN0aXNjaGUgYmVzbHVpdHZvcm1pbmcpLgoKLSBTdGF0aXN0aWVrIHNwZWVsdCBkYWFyb20gZWVuIGhlZWwgYmVsYW5ncmlqa2Ugcm9sIGluIHpvd2F0IGFsbGUgd2V0ZW5zY2hhcHBlbgoKCiMgW0hvbWVdKGh0dHBzOi8vZ3RwYi5naXRodWIuaW8vc2JjMjAvKSB7LX0K